[{"data":1,"prerenderedAt":1987},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-that-scales-with-container-size\u002F":3,"content-all-pages":1724},{"id":4,"title":5,"body":6,"description":1706,"extension":1707,"meta":1708,"navigation":313,"path":1720,"seo":1721,"stem":1722,"__hash__":1723},"content\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-that-scales-with-container-size\u002Findex.md","Motion That Scales with Container Size: cqi, cqb, and Derived Durations",{"type":7,"value":8,"toc":1697},"minimark",[9,13,45,48,53,61,75,86,88,92,99,210,214,379,851,861,885,887,891,894,932,970,1221,1237,1239,1243,1264,1275,1556,1567,1569,1573,1585,1599,1601,1605,1615,1624,1636,1651,1653,1657,1693],[10,11,5],"h1",{"id":12},"motion-that-scales-with-container-size-cqi-cqb-and-derived-durations",[14,15,16,17,21,22,25,26,29,30,33,34,39,40,44],"p",{},"A slide-in written as ",[18,19,20],"code",{},"translateX(300px)"," is really a statement about one particular layout — the one that happened to be on screen when the number was chosen. Put the same component into a 280px sidebar card and the declaration becomes absurd: the element travels further than the box that holds it, arriving either clipped by ",[18,23,24],{},"overflow: hidden"," or on top of whatever sits alongside. This page is about replacing that constant with a measurement the browser can take at style time — container query units in ",[18,27,28],{},"translate()"," and ",[18,31,32],{},"@keyframes",", plus durations computed from the same figure — so a single motion rule is correct at every width. It sits inside the ",[35,36,38],"a",{"href":37},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002F","container-aware motion"," section and depends directly on the unit mechanics set out in ",[35,41,43],{"href":42},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-units-cqi-cqb-explained\u002F","container query units cqi and cqb explained",".",[46,47],"hr",{},[49,50,52],"h2",{"id":51},"why-the-fixed-pixel-is-wrong-and-why-css-is-the-right-place-to-fix-it","Why the fixed pixel is wrong, and why CSS is the right place to fix it",[14,54,55,56,60],{},"The perceptual point is not that 300px is too many pixels. It is that the eye evaluates travel ",[57,58,59],"em",{},"relative to the moving object's surroundings",", in roughly the same way it evaluates type size relative to measure. A 300px slide across a 1200px hero covers a quarter of the space and reads as a considered entrance. The identical 300px inside a 280px card covers more than the whole component, and the brain does not interpret it as a bigger version of the same gesture — it interprets it as an error, a thing flying off. Somewhere between those two extremes the same number stops describing the same motion.",[14,62,63,64,67,68,70,71,74],{},"There are three ways to make travel track the box. A ",[18,65,66],{},"ResizeObserver"," can measure the element and write a custom property; that works, but it costs a script, an observation callback per component, and a frame of latency during which the old distance is still in effect — plus it can desynchronise from layout when the main thread is busy. Percentage values in ",[18,69,28],{}," are the classic CSS answer and are genuinely useful, but they resolve against ",[57,72,73],{},"the transformed element's own border box",", not its container, which is the wrong reference whenever the element does not fill its slot. Container query units resolve against the query container, which is exactly the reference the design intends, and they cost nothing beyond ordinary style computation.",[14,76,77,78,81,82,44],{},"The tradeoff worth stating plainly: container units make travel proportional, and proportional is not always what you want. A focus ring offset, a 1px border shift, or a checkbox tick should stay at a fixed size regardless of context, because they are absolute affordances rather than compositional gestures. Scale distances that describe ",[57,79,80],{},"layout relationships"," — entrances, reveals, panel slides, hover lifts — and leave absolute detail alone. And proportional travel has no lower bound of its own, so at very small container sizes it converges on zero-ish values that read as vibration rather than movement; that end of the range needs the explicit treatment described in ",[35,83,85],{"href":84},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers\u002F","suppressing motion in small containers",[46,87],{},[49,89,91],{"id":90},"complete-working-implementation","Complete working implementation",[14,93,94,95,98],{},"The example below is a direct comparison bench. Two identical rails each establish their own query container. The top marker animates a hard-coded 180px; the bottom animates ",[18,96,97],{},"70cqi",". At a wide frame both look fine. Drag the frame narrower and the top marker runs into and past the rail's clipping edge, while the bottom marker keeps stopping at 70% of whatever width the rail currently has.",[100,101,107,108,107,112,107,116,107,123,107,134,107,140,107,144,107,154,107,159,107,164,107,170,107,174,107,177,107,180,107,184,107,188,107,193],"svg",{"viewBox":102,"role":103,"ariaLabel":104,"xmlns":105,"style":106},"0 0 720 340","img","A fixed pixel travel distance overshooting a narrow container while a cqi-based distance stays inside it","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[109,110,111],"title",{},"Fixed travel versus container-relative travel",[113,114,115],"desc",{},"Two rails of equal width. The first animates a fixed three hundred pixel distance whose arrow passes the container edge; the second animates seventy cqi and its arrow stops inside the container.",[117,118,122],"text",{"x":119,"y":120,"style":121},"360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","Same rail, two distance units",[124,125],"line",{"x1":126,"y1":127,"x2":126,"y2":128,"stroke":129,"strokeWidth":130,"strokeDashArray":131},"320","56","284","#7aa2ff","2",[132,133],"6","5",[117,135,139],{"x":136,"y":137,"style":138},"430","46","text-anchor:middle;fill:#7aa2ff;font:12px sans-serif","container edge",[117,141,20],{"x":142,"y":127,"style":143},"40","text-anchor:start;fill:currentColor;font:12px ui-monospace,monospace;opacity:0.8",[145,146],"rect",{"x":142,"y":147,"width":148,"height":127,"rx":149,"fill":150,"stroke":151,"strokeWidth":152,"opacity":153},"64","280","8","none","currentColor","1.5","0.5",[145,155],{"x":156,"y":157,"width":158,"height":158,"rx":133,"fill":129},"52","80","24",[124,160],{"x1":156,"y1":161,"x2":162,"y2":161,"stroke":151,"strokeWidth":130,"markerEnd":163},"138","346","url(#cmv)",[117,165,169],{"x":166,"y":167,"style":168},"372","142","text-anchor:start;fill:currentColor;font:13px sans-serif;opacity:0.85","overshoots the rail",[117,171,173],{"x":142,"y":172,"style":143},"186","translateX(70cqi)",[145,175],{"x":142,"y":176,"width":148,"height":127,"rx":149,"fill":150,"stroke":151,"strokeWidth":152,"opacity":153},"194",[145,178],{"x":156,"y":179,"width":158,"height":158,"rx":133,"fill":129},"210",[124,181],{"x1":156,"y1":182,"x2":183,"y2":182,"stroke":151,"strokeWidth":130,"markerEnd":163},"268","244",[117,185,187],{"x":166,"y":186,"style":168},"272","always lands inside",[117,189,192],{"x":119,"y":190,"style":191},"318","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.6","the unit decides whether the rule survives a narrow slot",[194,195,196,197,107],"defs",{},"\n    ",[198,199,205,206,196],"marker",{"id":200,"markerWidth":201,"markerHeight":201,"refX":202,"refY":203,"orient":204},"cmv","9","7","4","auto","\n      ",[207,208],"path",{"d":209,"fill":151},"M0 0 L8 4 L0 8 z",[211,212],"live-demo",{"name":213},"cmotion-travel-units",[215,216,221],"pre",{"className":217,"code":218,"language":219,"meta":220,"style":220},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cdiv class=\"bench\">\n  \u003Cp class=\"bench__label\">travel: 180px (fixed)\u003C\u002Fp>\n  \u003Cdiv class=\"rail\">\u003Cspan class=\"marker marker--fixed\">\u003C\u002Fspan>\u003C\u002Fdiv>\n\n  \u003Cp class=\"bench__label\">travel: 70cqi (container-relative)\u003C\u002Fp>\n  \u003Cdiv class=\"rail\">\u003Cspan class=\"marker marker--fluid\">\u003C\u002Fspan>\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n","html","",[18,222,223,249,271,308,315,335,369],{"__ignoreMap":220},[224,225,227,231,235,239,242,246],"span",{"class":124,"line":226},1,[224,228,230],{"class":229},"suds8","\u003C",[224,232,234],{"class":233},"sne4z","div",[224,236,238],{"class":237},"s-5SL"," class",[224,240,241],{"class":229},"=",[224,243,245],{"class":244},"sT6z2","\"bench\"",[224,247,248],{"class":229},">\n",[224,250,252,255,257,259,261,264,267,269],{"class":124,"line":251},2,[224,253,254],{"class":229},"  \u003C",[224,256,14],{"class":233},[224,258,238],{"class":237},[224,260,241],{"class":229},[224,262,263],{"class":244},"\"bench__label\"",[224,265,266],{"class":229},">travel: 180px (fixed)\u003C\u002F",[224,268,14],{"class":233},[224,270,248],{"class":229},[224,272,274,276,278,280,282,285,288,290,292,294,297,300,302,304,306],{"class":124,"line":273},3,[224,275,254],{"class":229},[224,277,234],{"class":233},[224,279,238],{"class":237},[224,281,241],{"class":229},[224,283,284],{"class":244},"\"rail\"",[224,286,287],{"class":229},">\u003C",[224,289,224],{"class":233},[224,291,238],{"class":237},[224,293,241],{"class":229},[224,295,296],{"class":244},"\"marker marker--fixed\"",[224,298,299],{"class":229},">\u003C\u002F",[224,301,224],{"class":233},[224,303,299],{"class":229},[224,305,234],{"class":233},[224,307,248],{"class":229},[224,309,311],{"class":124,"line":310},4,[224,312,314],{"emptyLinePlaceholder":313},true,"\n",[224,316,318,320,322,324,326,328,331,333],{"class":124,"line":317},5,[224,319,254],{"class":229},[224,321,14],{"class":233},[224,323,238],{"class":237},[224,325,241],{"class":229},[224,327,263],{"class":244},[224,329,330],{"class":229},">travel: 70cqi (container-relative)\u003C\u002F",[224,332,14],{"class":233},[224,334,248],{"class":229},[224,336,338,340,342,344,346,348,350,352,354,356,359,361,363,365,367],{"class":124,"line":337},6,[224,339,254],{"class":229},[224,341,234],{"class":233},[224,343,238],{"class":237},[224,345,241],{"class":229},[224,347,284],{"class":244},[224,349,287],{"class":229},[224,351,224],{"class":233},[224,353,238],{"class":237},[224,355,241],{"class":229},[224,357,358],{"class":244},"\"marker marker--fluid\"",[224,360,299],{"class":229},[224,362,224],{"class":233},[224,364,299],{"class":229},[224,366,234],{"class":233},[224,368,248],{"class":229},[224,370,372,375,377],{"class":124,"line":371},7,[224,373,374],{"class":229},"\u003C\u002F",[224,376,234],{"class":233},[224,378,248],{"class":229},[215,380,384],{"className":381,"code":382,"language":383,"meta":220,"style":220},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast",".rail {\n  container-type: inline-size;   \u002F* each rail is its own query container *\u002F\n  position: relative;\n  height: 44px;\n  margin-bottom: 1.1rem;\n  border: 1px dashed var(--demo-border);\n  border-radius: 8px;\n  overflow: hidden;              \u002F* proves when the fixed run overshoots *\u002F\n}\n\n.marker {\n  position: absolute;\n  top: 10px; left: 10px;\n  width: 24px; height: 24px;\n  border-radius: 6px;\n  background: var(--demo-accent);\n}\n\n\u002F* Distance baked in at author time — wrong the moment the rail is narrow. *\u002F\n.marker--fixed { animation: run-fixed 2.4s ease-in-out infinite alternate; }\n@keyframes run-fixed { to { transform: translateX(180px); } }\n\n\u002F* Distance resolved against the rail's own inline size. *\u002F\n.marker--fluid { animation: run-fluid 2.4s ease-in-out infinite alternate; }\n@keyframes run-fluid { to { transform: translateX(70cqi); } }\n\n.bench__label {\n  margin: 0 0 .35rem;\n  color: var(--demo-muted);\n  font: 12px ui-monospace, monospace;\n}\n","css",[18,385,386,394,406,420,436,451,479,492,509,515,520,528,540,567,592,605,623,628,633,639,672,705,710,716,741,771,776,784,805,822,846],{"__ignoreMap":220},[224,387,388,391],{"class":124,"line":226},[224,389,390],{"class":237},".rail",[224,392,393],{"class":229}," {\n",[224,395,396,399,402],{"class":124,"line":251},[224,397,398],{"class":237},"  container-type",[224,400,401],{"class":229},": inline-size;   ",[224,403,405],{"class":404},"sLBg1","\u002F* each rail is its own query container *\u002F\n",[224,407,408,411,414,417],{"class":124,"line":273},[224,409,410],{"class":237},"  position",[224,412,413],{"class":229},": ",[224,415,416],{"class":237},"relative",[224,418,419],{"class":229},";\n",[224,421,422,425,427,430,434],{"class":124,"line":310},[224,423,424],{"class":237},"  height",[224,426,413],{"class":229},[224,428,429],{"class":237},"44",[224,431,433],{"class":432},"sHUrx","px",[224,435,419],{"class":229},[224,437,438,441,443,446,449],{"class":124,"line":317},[224,439,440],{"class":237},"  margin-bottom",[224,442,413],{"class":229},[224,444,445],{"class":237},"1.1",[224,447,448],{"class":432},"rem",[224,450,419],{"class":229},[224,452,453,456,458,461,463,466,469,472,476],{"class":124,"line":337},[224,454,455],{"class":237},"  border",[224,457,413],{"class":229},[224,459,460],{"class":237},"1",[224,462,433],{"class":432},[224,464,465],{"class":237}," dashed",[224,467,468],{"class":237}," var",[224,470,471],{"class":229},"(",[224,473,475],{"class":474},"soyes","--demo-border",[224,477,478],{"class":229},");\n",[224,480,481,484,486,488,490],{"class":124,"line":371},[224,482,483],{"class":237},"  border-radius",[224,485,413],{"class":229},[224,487,149],{"class":237},[224,489,433],{"class":432},[224,491,419],{"class":229},[224,493,495,498,500,503,506],{"class":124,"line":494},8,[224,496,497],{"class":237},"  overflow",[224,499,413],{"class":229},[224,501,502],{"class":237},"hidden",[224,504,505],{"class":229},";              ",[224,507,508],{"class":404},"\u002F* proves when the fixed run overshoots *\u002F\n",[224,510,512],{"class":124,"line":511},9,[224,513,514],{"class":229},"}\n",[224,516,518],{"class":124,"line":517},10,[224,519,314],{"emptyLinePlaceholder":313},[224,521,523,526],{"class":124,"line":522},11,[224,524,525],{"class":237},".marker",[224,527,393],{"class":229},[224,529,531,533,535,538],{"class":124,"line":530},12,[224,532,410],{"class":237},[224,534,413],{"class":229},[224,536,537],{"class":237},"absolute",[224,539,419],{"class":229},[224,541,543,546,548,551,553,556,559,561,563,565],{"class":124,"line":542},13,[224,544,545],{"class":237},"  top",[224,547,413],{"class":229},[224,549,550],{"class":237},"10",[224,552,433],{"class":432},[224,554,555],{"class":229},"; ",[224,557,558],{"class":237},"left",[224,560,413],{"class":229},[224,562,550],{"class":237},[224,564,433],{"class":432},[224,566,419],{"class":229},[224,568,570,573,575,577,579,581,584,586,588,590],{"class":124,"line":569},14,[224,571,572],{"class":237},"  width",[224,574,413],{"class":229},[224,576,158],{"class":237},[224,578,433],{"class":432},[224,580,555],{"class":229},[224,582,583],{"class":237},"height",[224,585,413],{"class":229},[224,587,158],{"class":237},[224,589,433],{"class":432},[224,591,419],{"class":229},[224,593,595,597,599,601,603],{"class":124,"line":594},15,[224,596,483],{"class":237},[224,598,413],{"class":229},[224,600,132],{"class":237},[224,602,433],{"class":432},[224,604,419],{"class":229},[224,606,608,611,613,616,618,621],{"class":124,"line":607},16,[224,609,610],{"class":237},"  background",[224,612,413],{"class":229},[224,614,615],{"class":237},"var",[224,617,471],{"class":229},[224,619,620],{"class":474},"--demo-accent",[224,622,478],{"class":229},[224,624,626],{"class":124,"line":625},17,[224,627,514],{"class":229},[224,629,631],{"class":124,"line":630},18,[224,632,314],{"emptyLinePlaceholder":313},[224,634,636],{"class":124,"line":635},19,[224,637,638],{"class":404},"\u002F* Distance baked in at author time — wrong the moment the rail is narrow. *\u002F\n",[224,640,642,645,648,651,654,657,660,663,666,669],{"class":124,"line":641},20,[224,643,644],{"class":237},".marker--fixed",[224,646,647],{"class":229}," { ",[224,649,650],{"class":237},"animation",[224,652,653],{"class":229},": run-fixed ",[224,655,656],{"class":237},"2.4",[224,658,659],{"class":432},"s",[224,661,662],{"class":237}," ease-in-out",[224,664,665],{"class":237}," infinite",[224,667,668],{"class":237}," alternate",[224,670,671],{"class":229},"; }\n",[224,673,675,677,680,682,685,687,690,692,695,697,700,702],{"class":124,"line":674},21,[224,676,32],{"class":432},[224,678,679],{"class":474}," run-fixed",[224,681,647],{"class":229},[224,683,684],{"class":237},"to",[224,686,647],{"class":229},[224,688,689],{"class":237},"transform",[224,691,413],{"class":229},[224,693,694],{"class":237},"translateX",[224,696,471],{"class":229},[224,698,699],{"class":237},"180",[224,701,433],{"class":432},[224,703,704],{"class":229},"); } }\n",[224,706,708],{"class":124,"line":707},22,[224,709,314],{"emptyLinePlaceholder":313},[224,711,713],{"class":124,"line":712},23,[224,714,715],{"class":404},"\u002F* Distance resolved against the rail's own inline size. *\u002F\n",[224,717,719,722,724,726,729,731,733,735,737,739],{"class":124,"line":718},24,[224,720,721],{"class":237},".marker--fluid",[224,723,647],{"class":229},[224,725,650],{"class":237},[224,727,728],{"class":229},": run-fluid ",[224,730,656],{"class":237},[224,732,659],{"class":432},[224,734,662],{"class":237},[224,736,665],{"class":237},[224,738,668],{"class":237},[224,740,671],{"class":229},[224,742,744,746,749,751,753,755,757,759,761,763,766,769],{"class":124,"line":743},25,[224,745,32],{"class":432},[224,747,748],{"class":474}," run-fluid",[224,750,647],{"class":229},[224,752,684],{"class":237},[224,754,647],{"class":229},[224,756,689],{"class":237},[224,758,413],{"class":229},[224,760,694],{"class":237},[224,762,471],{"class":229},[224,764,765],{"class":237},"70",[224,767,768],{"class":432},"cqi",[224,770,704],{"class":229},[224,772,774],{"class":124,"line":773},26,[224,775,314],{"emptyLinePlaceholder":313},[224,777,779,782],{"class":124,"line":778},27,[224,780,781],{"class":237},".bench__label",[224,783,393],{"class":229},[224,785,787,790,792,795,798,801,803],{"class":124,"line":786},28,[224,788,789],{"class":237},"  margin",[224,791,413],{"class":229},[224,793,794],{"class":237},"0",[224,796,797],{"class":237}," 0",[224,799,800],{"class":237}," .35",[224,802,448],{"class":432},[224,804,419],{"class":229},[224,806,808,811,813,815,817,820],{"class":124,"line":807},29,[224,809,810],{"class":237},"  color",[224,812,413],{"class":229},[224,814,615],{"class":237},[224,816,471],{"class":229},[224,818,819],{"class":474},"--demo-muted",[224,821,478],{"class":229},[224,823,825,828,830,833,835,838,841,844],{"class":124,"line":824},30,[224,826,827],{"class":237},"  font",[224,829,413],{"class":229},[224,831,832],{"class":237},"12",[224,834,433],{"class":432},[224,836,837],{"class":237}," ui-monospace",[224,839,840],{"class":229},", ",[224,842,843],{"class":237},"monospace",[224,845,419],{"class":229},[224,847,849],{"class":124,"line":848},31,[224,850,514],{"class":229},[852,853,854],"blockquote",{},[14,855,856,857,860],{},"The ",[18,858,859],{},"--demo-*"," values above are the theme variables supplied by the demo frame, so the\nexample follows light and dark mode here. Substitute your own colour tokens when you\ncopy it.",[14,862,863,864,867,868,870,871,873,874,877,878,880,881,884],{},"The important structural detail is that ",[18,865,866],{},"container-type: inline-size"," is on ",[18,869,390],{}," and the animated element is ",[18,872,525],{}," ",[57,875,876],{},"inside"," it. An element cannot query or measure against itself; the ",[18,879,97],{}," in the keyframe resolves against the nearest ancestor that is a query container. Drop the ",[18,882,883],{},"container-type"," line and the animation does not break — it silently starts measuring against the viewport instead, which is the single most confusing failure mode in this whole technique.",[46,886],{},[49,888,890],{"id":889},"the-key-technique-a-length-for-distance-a-ratio-for-time","The key technique: a length for distance, a ratio for time",[14,892,893],{},"Distance and duration need opposite treatments, and mixing them up is where most implementations fall over.",[14,895,896,873,900,902,903,906,907,840,910,840,913,840,916,919,920,923,924,927,928,931],{},[897,898,899],"strong",{},"Distance takes the unit directly.",[18,901,768],{}," is a ",[18,904,905],{},"\u003Clength>",", so it drops into ",[18,908,909],{},"translateX()",[18,911,912],{},"translateY()",[18,914,915],{},"inset",[18,917,918],{},"margin",", or a keyframe declaration with no conversion at all. ",[18,921,922],{},"transform: translateX(70cqi)"," is as valid as ",[18,925,926],{},"translateX(70px)",". There is no ",[18,929,930],{},"calc()"," required and no intermediate custom property needed.",[14,933,934,937,938,941,942,945,946,949,950,953,954,957,958,961,962,965,966,969],{},[897,935,936],{},"Duration cannot."," A ",[18,939,940],{},"\u003Ctime>"," cannot be produced by multiplying a length, so ",[18,943,944],{},"calc(400ms * 6cqi)"," is invalid, the declaration is dropped, and the element falls back to the initial ",[18,947,948],{},"0s"," — which looks exactly like having forgotten to write a transition at all. The fix is to reduce the container measurement to a ",[897,951,952],{},"unitless ratio"," first — but note that dividing a container unit by a number does not do it: ",[18,955,956],{},"1.6cqi \u002F 10"," is still a length, and ",[18,959,960],{},"clamp()"," will not mix a length with the plain numbers bounding it, so that whole declaration is invalid too. The conversion that works is ",[18,963,964],{},"tan(atan2(1cqi, 1px))",", which returns the ratio of two lengths as a real ",[18,967,968],{},"\u003Cnumber>",". Bound that, then multiply a base time by it:",[215,971,973],{"className":381,"code":972,"language":383,"meta":220,"style":220},".panel {\n  \u002F* tan(atan2()) turns the container length into a real number; clamp bounds it to 0.5 – 1.4. *\u002F\n  --cqi-ratio: tan(atan2(1cqi, 1px));\n  --room: clamp(0.5, calc(var(--cqi-ratio) * 0.16), 1.4);\n\n  --slide: clamp(12px, 8cqi, 64px);        \u002F* a length, used directly *\u002F\n  --beat:  calc(140ms * var(--room));      \u002F* a time, built from the ratio *\u002F\n\n  transition: transform var(--beat) cubic-bezier(.2, .8, .2, 1);\n}\n.panel[data-open] { transform: translateX(calc(-1 * var(--slide))); }\n",[18,974,975,982,987,1017,1062,1066,1099,1133,1137,1177,1181],{"__ignoreMap":220},[224,976,977,980],{"class":124,"line":226},[224,978,979],{"class":237},".panel",[224,981,393],{"class":229},[224,983,984],{"class":124,"line":251},[224,985,986],{"class":404},"  \u002F* tan(atan2()) turns the container length into a real number; clamp bounds it to 0.5 – 1.4. *\u002F\n",[224,988,989,992,994,997,999,1002,1004,1006,1008,1010,1012,1014],{"class":124,"line":273},[224,990,991],{"class":474},"  --cqi-ratio",[224,993,413],{"class":229},[224,995,996],{"class":237},"tan",[224,998,471],{"class":229},[224,1000,1001],{"class":237},"atan2",[224,1003,471],{"class":229},[224,1005,460],{"class":237},[224,1007,768],{"class":432},[224,1009,840],{"class":229},[224,1011,460],{"class":237},[224,1013,433],{"class":432},[224,1015,1016],{"class":229},"));\n",[224,1018,1019,1022,1024,1027,1029,1031,1033,1036,1038,1040,1042,1045,1048,1051,1054,1057,1060],{"class":124,"line":310},[224,1020,1021],{"class":474},"  --room",[224,1023,413],{"class":229},[224,1025,1026],{"class":237},"clamp",[224,1028,471],{"class":229},[224,1030,153],{"class":237},[224,1032,840],{"class":229},[224,1034,1035],{"class":237},"calc",[224,1037,471],{"class":229},[224,1039,615],{"class":237},[224,1041,471],{"class":229},[224,1043,1044],{"class":474},"--cqi-ratio",[224,1046,1047],{"class":229},") ",[224,1049,1050],{"class":432},"*",[224,1052,1053],{"class":237}," 0.16",[224,1055,1056],{"class":229},"), ",[224,1058,1059],{"class":237},"1.4",[224,1061,478],{"class":229},[224,1063,1064],{"class":124,"line":317},[224,1065,314],{"emptyLinePlaceholder":313},[224,1067,1068,1071,1073,1075,1077,1079,1081,1083,1085,1087,1089,1091,1093,1096],{"class":124,"line":337},[224,1069,1070],{"class":474},"  --slide",[224,1072,413],{"class":229},[224,1074,1026],{"class":237},[224,1076,471],{"class":229},[224,1078,832],{"class":237},[224,1080,433],{"class":432},[224,1082,840],{"class":229},[224,1084,149],{"class":237},[224,1086,768],{"class":432},[224,1088,840],{"class":229},[224,1090,147],{"class":237},[224,1092,433],{"class":432},[224,1094,1095],{"class":229},");        ",[224,1097,1098],{"class":404},"\u002F* a length, used directly *\u002F\n",[224,1100,1101,1104,1107,1109,1111,1114,1117,1120,1122,1124,1127,1130],{"class":124,"line":371},[224,1102,1103],{"class":474},"  --beat",[224,1105,1106],{"class":229},":  ",[224,1108,1035],{"class":237},[224,1110,471],{"class":229},[224,1112,1113],{"class":237},"140",[224,1115,1116],{"class":432},"ms",[224,1118,1119],{"class":432}," *",[224,1121,468],{"class":237},[224,1123,471],{"class":229},[224,1125,1126],{"class":474},"--room",[224,1128,1129],{"class":229},"));      ",[224,1131,1132],{"class":404},"\u002F* a time, built from the ratio *\u002F\n",[224,1134,1135],{"class":124,"line":494},[224,1136,314],{"emptyLinePlaceholder":313},[224,1138,1139,1142,1145,1147,1149,1152,1154,1157,1159,1162,1164,1167,1169,1171,1173,1175],{"class":124,"line":511},[224,1140,1141],{"class":237},"  transition",[224,1143,1144],{"class":229},": transform ",[224,1146,615],{"class":237},[224,1148,471],{"class":229},[224,1150,1151],{"class":474},"--beat",[224,1153,1047],{"class":229},[224,1155,1156],{"class":237},"cubic-bezier",[224,1158,471],{"class":229},[224,1160,1161],{"class":237},".2",[224,1163,840],{"class":229},[224,1165,1166],{"class":237},".8",[224,1168,840],{"class":229},[224,1170,1161],{"class":237},[224,1172,840],{"class":229},[224,1174,460],{"class":237},[224,1176,478],{"class":229},[224,1178,1179],{"class":124,"line":517},[224,1180,514],{"class":229},[224,1182,1183,1185,1188,1191,1194,1196,1198,1200,1202,1204,1206,1209,1211,1213,1215,1218],{"class":124,"line":522},[224,1184,979],{"class":237},[224,1186,1187],{"class":229},"[",[224,1189,1190],{"class":237},"data-open",[224,1192,1193],{"class":229},"] { ",[224,1195,689],{"class":237},[224,1197,413],{"class":229},[224,1199,694],{"class":237},[224,1201,471],{"class":229},[224,1203,1035],{"class":237},[224,1205,471],{"class":229},[224,1207,1208],{"class":237},"-1",[224,1210,1119],{"class":432},[224,1212,468],{"class":237},[224,1214,471],{"class":229},[224,1216,1217],{"class":474},"--slide",[224,1219,1220],{"class":229},"))); }\n",[14,1222,856,1223,1225,1226,1228,1229,1232,1233,44],{},[18,1224,960],{}," around the distance is doing separate work from the ",[18,1227,960],{}," around the ratio. The distance clamp stops the gesture becoming either invisible in a tiny box or theatrical in a very wide one. The ratio clamp keeps the duration inside the range where interaction still feels responsive — a purely proportional duration in a 1600px container would stretch past the point where a hover response feels immediate. Pairing a longer distance with a longer time is what keeps ",[57,1230,1231],{},"velocity"," constant, which is the quantity the eye is actually judging; the easing curve choice that goes with it is covered in ",[35,1234,1236],{"href":1235},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions\u002F","CSS transition timing functions",[46,1238],{},[49,1240,1242],{"id":1241},"variation-vertical-travel-and-why-cqb-is-usually-the-wrong-reach","Variation: vertical travel, and why cqb is usually the wrong reach",[14,1244,1245,1246,1249,1250,1253,1254,1256,1257,1259,1260,44],{},"The obvious move for a vertical slide is ",[18,1247,1248],{},"cqb",", which measures 1% of the container's block size. It works, but it carries a condition: block-axis measurement requires ",[18,1251,1252],{},"container-type: size",", which applies containment on both axes and therefore demands that the container have a determinate height. Applied to an ordinary auto-height card, ",[18,1255,1252],{}," collapses the box to nothing, and the resulting bug — a container that measures zero, so every ",[18,1258,1248],{}," distance is zero, so nothing moves — is deeply unfun to diagnose. The distinction is worked through in ",[35,1261,1263],{"href":1262},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size\u002F","container-type: size vs inline-size",[14,1265,1266,1267,1270,1271,1274],{},"In practice, sizing ",[57,1268,1269],{},"vertical"," travel from the ",[57,1272,1273],{},"inline"," axis is both safe and defensible: a component that is wide is generally a component with room, and vertical entrance distances that scale with width look correct because the component's overall scale is what changed.",[215,1276,1278],{"className":381,"code":1277,"language":383,"meta":220,"style":220},"\u002F* Vertical entrance whose distance follows the container's width. *\u002F\n.notice { animation: rise-in 320ms cubic-bezier(.2, .8, .2, 1) both; }\n\n@keyframes rise-in {\n  from { opacity: 0; transform: translateY(clamp(8px, 4cqi, 28px)); }\n  to   { opacity: 1; transform: translateY(0); }\n}\n\n\u002F* Reserve cqb for containers that genuinely have a fixed height. *\u002F\n.viewport-strip {\n  container-type: size;\n  block-size: 320px;               \u002F* determinate — required for cqb *\u002F\n}\n.viewport-strip .ticker { animation: drop 5s linear infinite; }\n@keyframes drop { to { transform: translateY(90cqb); } }\n\n@media (prefers-reduced-motion: reduce) {\n  .notice, .viewport-strip .ticker { animation: none; }\n}\n",[18,1279,1280,1285,1327,1331,1340,1389,1418,1422,1426,1431,1438,1445,1462,1466,1491,1519,1523,1531,1552],{"__ignoreMap":220},[224,1281,1282],{"class":124,"line":226},[224,1283,1284],{"class":404},"\u002F* Vertical entrance whose distance follows the container's width. *\u002F\n",[224,1286,1287,1290,1292,1294,1297,1299,1301,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1325],{"class":124,"line":251},[224,1288,1289],{"class":237},".notice",[224,1291,647],{"class":229},[224,1293,650],{"class":237},[224,1295,1296],{"class":229},": rise-in ",[224,1298,126],{"class":237},[224,1300,1116],{"class":432},[224,1302,1303],{"class":237}," cubic-bezier",[224,1305,471],{"class":229},[224,1307,1161],{"class":237},[224,1309,840],{"class":229},[224,1311,1166],{"class":237},[224,1313,840],{"class":229},[224,1315,1161],{"class":237},[224,1317,840],{"class":229},[224,1319,460],{"class":237},[224,1321,1047],{"class":229},[224,1323,1324],{"class":237},"both",[224,1326,671],{"class":229},[224,1328,1329],{"class":124,"line":273},[224,1330,314],{"emptyLinePlaceholder":313},[224,1332,1333,1335,1338],{"class":124,"line":310},[224,1334,32],{"class":432},[224,1336,1337],{"class":474}," rise-in",[224,1339,393],{"class":229},[224,1341,1342,1345,1347,1350,1352,1354,1356,1358,1360,1363,1365,1367,1369,1371,1373,1375,1377,1379,1381,1384,1386],{"class":124,"line":317},[224,1343,1344],{"class":237},"  from",[224,1346,647],{"class":229},[224,1348,1349],{"class":237},"opacity",[224,1351,413],{"class":229},[224,1353,794],{"class":237},[224,1355,555],{"class":229},[224,1357,689],{"class":237},[224,1359,413],{"class":229},[224,1361,1362],{"class":237},"translateY",[224,1364,471],{"class":229},[224,1366,1026],{"class":237},[224,1368,471],{"class":229},[224,1370,149],{"class":237},[224,1372,433],{"class":432},[224,1374,840],{"class":229},[224,1376,203],{"class":237},[224,1378,768],{"class":432},[224,1380,840],{"class":229},[224,1382,1383],{"class":237},"28",[224,1385,433],{"class":432},[224,1387,1388],{"class":229},")); }\n",[224,1390,1391,1394,1397,1399,1401,1403,1405,1407,1409,1411,1413,1415],{"class":124,"line":337},[224,1392,1393],{"class":237},"  to",[224,1395,1396],{"class":229},"   { ",[224,1398,1349],{"class":237},[224,1400,413],{"class":229},[224,1402,460],{"class":237},[224,1404,555],{"class":229},[224,1406,689],{"class":237},[224,1408,413],{"class":229},[224,1410,1362],{"class":237},[224,1412,471],{"class":229},[224,1414,794],{"class":237},[224,1416,1417],{"class":229},"); }\n",[224,1419,1420],{"class":124,"line":371},[224,1421,514],{"class":229},[224,1423,1424],{"class":124,"line":494},[224,1425,314],{"emptyLinePlaceholder":313},[224,1427,1428],{"class":124,"line":511},[224,1429,1430],{"class":404},"\u002F* Reserve cqb for containers that genuinely have a fixed height. *\u002F\n",[224,1432,1433,1436],{"class":124,"line":517},[224,1434,1435],{"class":237},".viewport-strip",[224,1437,393],{"class":229},[224,1439,1440,1442],{"class":124,"line":522},[224,1441,398],{"class":237},[224,1443,1444],{"class":229},": size;\n",[224,1446,1447,1450,1452,1454,1456,1459],{"class":124,"line":530},[224,1448,1449],{"class":237},"  block-size",[224,1451,413],{"class":229},[224,1453,126],{"class":237},[224,1455,433],{"class":432},[224,1457,1458],{"class":229},";               ",[224,1460,1461],{"class":404},"\u002F* determinate — required for cqb *\u002F\n",[224,1463,1464],{"class":124,"line":542},[224,1465,514],{"class":229},[224,1467,1468,1470,1473,1475,1477,1480,1482,1484,1487,1489],{"class":124,"line":569},[224,1469,1435],{"class":237},[224,1471,1472],{"class":237}," .ticker",[224,1474,647],{"class":229},[224,1476,650],{"class":237},[224,1478,1479],{"class":229},": drop ",[224,1481,133],{"class":237},[224,1483,659],{"class":432},[224,1485,1486],{"class":237}," linear",[224,1488,665],{"class":237},[224,1490,671],{"class":229},[224,1492,1493,1495,1498,1500,1502,1504,1506,1508,1510,1512,1515,1517],{"class":124,"line":594},[224,1494,32],{"class":432},[224,1496,1497],{"class":474}," drop",[224,1499,647],{"class":229},[224,1501,684],{"class":237},[224,1503,647],{"class":229},[224,1505,689],{"class":237},[224,1507,413],{"class":229},[224,1509,1362],{"class":237},[224,1511,471],{"class":229},[224,1513,1514],{"class":237},"90",[224,1516,1248],{"class":432},[224,1518,704],{"class":229},[224,1520,1521],{"class":124,"line":607},[224,1522,314],{"emptyLinePlaceholder":313},[224,1524,1525,1528],{"class":124,"line":625},[224,1526,1527],{"class":432},"@media",[224,1529,1530],{"class":229}," (prefers-reduced-motion: reduce) {\n",[224,1532,1533,1536,1538,1540,1542,1544,1546,1548,1550],{"class":124,"line":630},[224,1534,1535],{"class":237},"  .notice",[224,1537,840],{"class":229},[224,1539,1435],{"class":237},[224,1541,1472],{"class":237},[224,1543,647],{"class":229},[224,1545,650],{"class":237},[224,1547,413],{"class":229},[224,1549,150],{"class":237},[224,1551,671],{"class":229},[224,1553,1554],{"class":124,"line":635},[224,1555,514],{"class":229},[14,1557,1558,1559,1562,1563,44],{},"The reduced-motion block is not optional decoration. Proportional travel produces ",[57,1560,1561],{},"larger"," movements in exactly the contexts — wide, full-bleed regions — where large movements are most likely to cause discomfort, so the preference override matters more here than it does with fixed distances. The full set of override shapes is in ",[35,1564,1566],{"href":1565},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Freducing-motion-preferences-in-css\u002F","reducing motion preferences in CSS",[46,1568],{},[49,1570,1572],{"id":1571},"browser-support","Browser support",[14,1574,1575,1576,1578,1579,1581,1582,1584],{},"Container query units ship with size container queries and have the same support floor: Chrome and Edge 105+, Safari 16+, Firefox 110+, giving interoperable support since Firefox's release in February 2023. Their use inside ",[18,1577,689],{}," and inside ",[18,1580,32],{}," is not a separate feature — they are lengths, and every engine that resolves them resolves them everywhere a length is accepted. ",[18,1583,960],{}," predates all of this comfortably and is supported across every current engine.",[14,1586,1587,1588,1590,1591,1594,1595,44],{},"The graceful-degradation story is unusually benign. In an engine without container query support, ",[18,1589,97],{}," falls back to the equivalent small-viewport unit rather than being discarded, so motion still happens — it is simply sized against the window. If you need something better than \"wrong reference but still animated\", gate the proportional rules behind ",[18,1592,1593],{},"@supports (container-type: inline-size)"," and supply a fixed-pixel default outside it, as set out in ",[35,1596,1598],{"href":1597},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports\u002F","feature detection with @supports",[46,1600],{},[49,1602,1604],{"id":1603},"faq","FAQ",[14,1606,1607,1610,1611,1614],{},[897,1608,1609],{},"Why does a 300px slide look wrong in a 280px card?","\nThe travel exceeds the component itself, so the element leaves its own box and either clips against ",[18,1612,1613],{},"overflow"," or overlaps its neighbours. Even at 200px the movement reads as the whole component jumping rather than a detail sliding, because the eye judges travel as a fraction of the moving object's container.",[14,1616,1617,1620,1621,1623],{},[897,1618,1619],{},"Can container query units appear inside @keyframes?","\nYes. Keyframe declarations accept lengths like any other declaration, so ",[18,1622,922],{}," inside a keyframe is valid and resolves against the animated element's query container at style computation time.",[14,1625,1626,1629,1630,1632,1633,1635],{},[897,1627,1628],{},"How do I turn a container width into an animation duration?","\nDivide the container unit down into a unitless ratio inside ",[18,1631,960],{},", then multiply a base time by that ratio with ",[18,1634,930],{},". A length can never be multiplied directly into a time value, so the intermediate unitless step is mandatory.",[14,1637,1638,1641,1642,1644,1645,1647,1648,1650],{},[897,1639,1640],{},"Should I use cqi or cqb for vertical movement?","\nUsually ",[18,1643,768],{}," even for vertical movement, because ",[18,1646,1248],{}," requires ",[18,1649,1252],{},", which contains the block axis and needs a determinate height. Sizing vertical travel from the inline axis is stable and avoids the collapsed-container problem.",[46,1652],{},[49,1654,1656],{"id":1655},"related","Related",[1658,1659,1660,1667,1673,1679,1686],"ul",{},[1661,1662,1663,1666],"li",{},[35,1664,1665],{"href":37},"Container-Aware Motion"," — the parent section on sizing motion to the component's own box.",[1661,1668,1669,1672],{},[35,1670,1671],{"href":84},"Suppressing Motion in Small Containers"," — what to do at the bottom of the scale, where proportional travel stops reading.",[1661,1674,1675,1678],{},[35,1676,1677],{"href":42},"Container Query Units cqi and cqb Explained"," — the cross-area reference for the units used throughout.",[1661,1680,1681,1685],{},[35,1682,1684],{"href":1683},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-space-scale-with-clamp\u002F","Fluid Space Scale with clamp()"," — the same clamping arithmetic applied to spacing tokens.",[1661,1687,1688,1692],{},[35,1689,1691],{"href":1690},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations\u002F","Fluid Spacing Tokens Driving Transition Durations"," — sharing one token between layout and timing across a design system.",[1694,1695,1696],"style",{},"html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}",{"title":220,"searchDepth":251,"depth":251,"links":1698},[1699,1700,1701,1702,1703,1704,1705],{"id":51,"depth":251,"text":52},{"id":90,"depth":251,"text":91},{"id":889,"depth":251,"text":890},{"id":1241,"depth":251,"text":1242},{"id":1571,"depth":251,"text":1572},{"id":1603,"depth":251,"text":1604},{"id":1655,"depth":251,"text":1656},"Use cqi and cqb inside translate() and @keyframes so animation travel scales with the container, and derive duration from the same measurement with calc().","md",{"pageTitle":1709,"datePublished":1710,"dateModified":1710,"faq":1711},"Motion That Scales with Container Size","2026-07-20",[1712,1714,1716,1718],{"q":1609,"a":1713},"The travel exceeds the component itself, so the element leaves its own box and either clips against overflow or overlaps its neighbours. Even at 200px the movement reads as the whole component jumping rather than a detail sliding, because the eye judges travel as a fraction of the moving object's container.",{"q":1619,"a":1715},"Yes. Keyframe declarations accept lengths like any other declaration, so transform: translateX(70cqi) inside a keyframe is valid and resolves against the animated element's query container at style computation time.",{"q":1628,"a":1717},"Divide the container unit down into a unitless ratio inside clamp(), then multiply a base time by that ratio with calc(). A length can never be multiplied directly into a time value, so the intermediate unitless step is mandatory.",{"q":1640,"a":1719},"Usually cqi even for vertical movement, because cqb requires container-type: size which contains the block axis and needs a determinate height. Sizing vertical travel from the inline axis is stable and avoids the collapsed-container problem.","\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-that-scales-with-container-size",{"title":5,"description":1706},"css-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-that-scales-with-container-size\u002Findex","3CQboQuaUxIbmaovwVrYfLmpXgo46_Di1Uc_Di4r_Z0",[1725,1728,1731,1734,1737,1740,1743,1746,1749,1752,1753,1756,1759,1762,1765,1768,1771,1774,1777,1780,1783,1786,1789,1792,1795,1798,1801,1804,1807,1810,1813,1816,1819,1822,1825,1828,1831,1834,1837,1840,1843,1846,1849,1852,1855,1858,1861,1864,1867,1870,1873,1876,1879,1882,1885,1888,1891,1894,1897,1900,1903,1906,1909,1912,1915,1918,1921,1924,1927,1930,1933,1936,1939,1942,1945,1948,1951,1954,1957,1960,1963,1966,1969,1972,1975,1978,1981,1984],{"path":1726,"title":1727},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fcreating-accessible-focus-indicators","Creating Accessible Focus Indicators: Building a Ring That Survives Any Background",{"path":1729,"title":1730},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1732,"title":1733},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1735,"title":1736},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Freducing-motion-preferences-in-css","Reducing Motion Preferences in CSS: How the Setting Becomes a Media Feature",{"path":1738,"title":1739},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Ftarget-size-and-pointer-accessibility","Target Size and Pointer Accessibility: Meeting 2.5.8 Without Redesigning",{"path":1741,"title":1742},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1744,"title":1745},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1747,"title":1748},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1750,"title":1751},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1720,"title":5},{"path":1754,"title":1755},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":1757,"title":1758},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1760,"title":1761},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwhen-to-use-javascript-animation","When to Use JavaScript Instead of CSS for Animation",{"path":1763,"title":1764},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fanimating-custom-properties-with-at-property","Animating Custom Properties with @property: Typed Variables That Interpolate",{"path":1766,"title":1767},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1769,"title":1770},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1772,"title":1773},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fregistered-properties-and-type-safety","Registered Properties and Type Safety: @property as a Contract for Design Tokens",{"path":1775,"title":1776},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1778,"title":1779},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1781,"title":1782},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1784,"title":1785},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1787,"title":1788},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1790,"title":1791},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-visible-vs-focus-polyfill-alternatives"," vs :focus: Why It Replaced the Focus-Ring Polyfill",{"path":1793,"title":1794},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1796,"title":1797},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1799,"title":1800},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fpointer-and-hover-media-queries","Pointer and Hover Media Queries: Gating Affordances by Input Capability",{"path":1802,"title":1803},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fsmooth-hover-effects-without-javascript","Smooth Hover Effects Without JavaScript: CSS-Only Patterns for Modern UI",{"path":1805,"title":1806},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1808,"title":1809},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1811,"title":1812},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1814,"title":1815},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-loading-spinners-and-skeletons","CSS-Only Loading Spinners and Skeleton Shimmer Screens with @keyframes",{"path":1817,"title":1818},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-toggle-switches-and-checkboxes","CSS-Only Toggle Switches and Checkboxes That Keep the Native Input",{"path":1820,"title":1821},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1823,"title":1824},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1826,"title":1827},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1829,"title":1830},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1832,"title":1833},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fprofiling-animations-in-devtools","Profiling CSS Animations in DevTools: Finding the Frame That Costs Too Much",{"path":1835,"title":1836},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fwill-change-and-the-compositor-thread","will-change and the Compositor Thread: Layer Promotion Without the Footguns",{"path":1838,"title":1839},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1841,"title":1842},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1844,"title":1845},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1847,"title":1848},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1850,"title":1851},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1853,"title":1854},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fsame-document-view-transitions","Writing a Same-Document View Transition: the CSS You Actually Author",{"path":1856,"title":1857},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-names-shared-elements","view-transition-name and Shared Elements: Morphing a Thumbnail into a Hero",{"path":1859,"title":1860},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":1862,"title":1863},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":1865,"title":1866},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1868,"title":1869},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1871,"title":1872},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1874,"title":1875},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1877,"title":1878},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1880,"title":1881},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1883,"title":1884},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1886,"title":1887},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-units-cqi-cqb-explained","Container Query Units Explained: cqi, cqb, cqw, cqh, cqmin and cqmax",{"path":1889,"title":1890},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1892,"title":1893},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1895,"title":1896},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fhow-to-use-container-queries-in-production","How to Use Container Queries in Production Without a Rewrite",{"path":1898,"title":1899},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1901,"title":1902},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1904,"title":1905},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1907,"title":1908},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fbuilding-a-dashboard-with-subgrid","Building a Responsive Dashboard Where Cards Align with Subgrid",{"path":1910,"title":1911},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fholy-grail-layout-with-grid","The Holy-Grail Layout with CSS Grid and Container Queries",{"path":1913,"title":1914},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1916,"title":1917},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1919,"title":1920},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fclamp-vs-media-query-typography","clamp() Fluid Type vs Media-Query Step Typography: Tradeoffs and Anatomy",{"path":1922,"title":1923},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-space-scale-with-clamp","Building a Fluid Spacing Scale with clamp() and Container Units",{"path":1925,"title":1926},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1928,"title":1929},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1931,"title":1932},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1934,"title":1935},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1937,"title":1938},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1940,"title":1941},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1943,"title":1944},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1946,"title":1947},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1949,"title":1950},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1952,"title":1953},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1955,"title":1956},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1958,"title":1959},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fbuilding-responsive-cards-with-container-queries","Building Responsive Cards with Container Queries: A Production-Ready Guide",{"path":1961,"title":1962},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1964,"title":1965},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":1967,"title":1968},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":1970,"title":1971},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":1973,"title":1974},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":1976,"title":1977},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcontainer-style-query-theming","Container Style Query Theming: One Token Instead of a Variant Class Matrix",{"path":1979,"title":1980},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":1982,"title":1983},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-queries-with-custom-properties","Style Queries With Custom Properties: Declaring, Inheriting, and Matching Tokens",{"path":1985,"title":1986},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-fallbacks-and-support","Style Query Fallbacks and Support: Designing for Older Browser Versions",1784566157498]