[{"data":1,"prerenderedAt":2972},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion":3,"content-all-pages":2711},{"id":4,"title":5,"body":6,"description":2693,"extension":2694,"meta":2695,"navigation":732,"path":2707,"seo":2708,"stem":2709,"__hash__":2710},"content\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Findex.md","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"type":7,"value":8,"toc":2673},"minimark",[9,13,42,50,55,83,86,91,94,185,188,190,194,307,310,341,357,360,368,370,374,552,579,581,585,590,600,641,645,651,786,790,801,931,935,941,1152,1159,1163,1167,1170,1247,1254,1258,1261,1324,1326,1330,1333,1336,1525,2097,2107,2126,2142,2144,2148,2168,2180,2191,2200,2222,2224,2228,2231,2301,2303,2307,2425,2445,2447,2451,2566,2568,2572,2581,2603,2609,2618,2620,2624,2669],[10,11,5],"h1",{"id":12},"container-aware-motion-animation-sized-by-the-space-a-component-actually-has",[14,15,16,17,21,22,25,26,31,32,36,37,41],"p",{},"A component almost never knows where it will land. The same product card ships into a full-bleed marketing row, a three-up grid, and a 280px filter rail, and in each of those places the ",[18,19,20],"em",{},"layout"," adapts perfectly well while the ",[18,23,24],{},"motion"," does not: the hover lift, the slide-in offset, and the reveal distance were all written once, in pixels, against whatever width the author happened to have on screen that afternoon. This guide, part of the ",[27,28,30],"a",{"href":29},"\u002Fcss-only-micro-interactions-animations\u002F","CSS-only micro-interactions and animations"," area, is about closing that gap — treating movement as something measured against the component's own box rather than the browser window, using ",[33,34,35],"code",{},"@container"," and container query units. It leans heavily on the mechanics documented across ",[27,38,40],{"href":39},"\u002Fmastering-container-queries-responsive-layouts\u002F","Mastering Container Queries & Responsive Layouts",", because container-aware motion is that area's tooling pointed at a different problem.",[14,43,44,45,49],{},"The governing idea is a ",[46,47,48],"strong",{},"motion budget",": every box has an amount of movement it can absorb before movement stops reading as movement. A 40px slide inside a 700px hero is a gesture. The same 40px slide inside a 240px card is a fifth of the component lurching sideways, and readers perceive it as a glitch rather than a transition. Container-aware motion makes that budget explicit and lets the box compute it.",[14,51,52],{},[46,53,54],{},"What this section covers:",[56,57,58,70,77,80],"ul",{},[59,60,61,62,65,66,69],"li",{},"Deriving travel distance from ",[33,63,64],{},"cqi"," and ",[33,67,68],{},"cqb"," so a component moves proportionally in any slot.",[59,71,72,73,76],{},"Switching the ",[18,74,75],{},"kind"," of affordance — hover-reveal versus persistent control — on container width.",[59,78,79],{},"Removing motion entirely below a size floor, and layering that with user motion preferences.",[59,81,82],{},"The debugging and support story for shipping this in production.",[84,85],"hr",{},[87,88,90],"h2",{"id":89},"prerequisites","Prerequisites",[14,92,93],{},"You should already be comfortable with:",[56,95,96,111,133,155,173],{},[59,97,98,101,102,105,106,110],{},[46,99,100],{},"Declaring a query container."," ",[33,103,104],{},"container-type: inline-size"," on an ancestor, and why an element can never query itself. The ",[27,107,109],{"href":108},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002F","container query syntax basics"," guide covers the rule shape and matching model.",[59,112,113,123,124,127,128,132],{},[46,114,115,116,65,119,122],{},"The difference between ",[33,117,118],{},"size",[33,120,121],{},"inline-size"," containment",", including the block-size collapse that ",[33,125,126],{},"container-type: size"," forces — see ",[27,129,131],{"href":130},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size\u002F","container-type: size vs inline-size",".",[59,134,135,101,138,140,141,140,143,146,147,150,151,132],{},[46,136,137],{},"Container query units.",[33,139,64],{},", ",[33,142,68],{},[33,144,145],{},"cqmin",", and ",[33,148,149],{},"cqmax"," and what each resolves against, from ",[27,152,154],{"href":153},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-units-cqi-cqb-explained\u002F","container query units cqi and cqb explained",[59,156,157,160,161,164,165,168,169,132],{},[46,158,159],{},"Transition and keyframe fundamentals"," — the ",[33,162,163],{},"transition"," shorthand, ",[33,166,167],{},"@keyframes",", and easing choice as discussed in ",[27,170,172],{"href":171},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions\u002F","CSS transition timing functions",[59,174,175,180,181,132],{},[46,176,177],{},[33,178,179],{},"prefers-reduced-motion"," as a hard constraint rather than a nicety, per ",[27,182,184],{"href":183},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Freducing-motion-preferences-in-css\u002F","reducing motion preferences in CSS",[14,186,187],{},"Nothing here needs JavaScript, a build step, or a preprocessor.",[84,189],{},[87,191,193],{"id":192},"the-core-concept-movement-measured-against-the-containing-box","The core concept: movement measured against the containing box",[195,196,202,203,202,207,202,211,202,218,202,229,202,235,202,240,202,245,202,253,202,258,202,261,202,264,202,267,202,270,202,274,202,277,202,280,202,284,202,287,202,290,202,294,202,297,202,302],"svg",{"viewBox":197,"role":198,"ariaLabel":199,"xmlns":200,"style":201},"0 0 720 320","img","The same component in three container widths, each resolving the same cqi-based travel distance to a different pixel value","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[204,205,206],"title",{},"One motion rule, three container widths",[208,209,210],"desc",{},"Three cards representing narrow, medium and wide containers. Each declares the same six cqi travel distance, which resolves to fourteen, twenty-five and forty-two pixels respectively, shown as bars of proportional length.",[212,213,217],"text",{"x":214,"y":215,"style":216},"360","30","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","One rule, three resolved distances",[219,220],"rect",{"x":215,"y":221,"width":222,"height":223,"rx":224,"fill":225,"stroke":226,"strokeWidth":227,"opacity":228},"60","200","150","12","none","currentColor","1.5","0.5",[212,230,234],{"x":231,"y":232,"style":233},"130","92","text-anchor:middle;fill:currentColor;font:600 13px sans-serif","narrow slot",[212,236,239],{"x":231,"y":237,"style":238},"116","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace;opacity:0.75","240px box",[212,241,244],{"x":231,"y":242,"style":243},"142","text-anchor:middle;fill:#7aa2ff;font:12px ui-monospace,monospace","6cqi = 14px",[219,246],{"x":247,"y":248,"width":215,"height":249,"rx":250,"fill":251,"opacity":252},"115","158","14","4","#7aa2ff","0.85",[212,254,257],{"x":231,"y":255,"style":256},"196","text-anchor:middle;fill:currentColor;font:11px sans-serif;opacity:0.65","a small, calm move",[219,259],{"x":260,"y":221,"width":222,"height":223,"rx":224,"fill":225,"stroke":226,"strokeWidth":227,"opacity":228},"260",[212,262,263],{"x":214,"y":232,"style":233},"grid cell",[212,265,266],{"x":214,"y":237,"style":238},"420px box",[212,268,269],{"x":214,"y":242,"style":243},"6cqi = 25px",[219,271],{"x":272,"y":248,"width":273,"height":249,"rx":250,"fill":251,"opacity":252},"335","50",[212,275,276],{"x":214,"y":255,"style":256},"a readable gesture",[219,278],{"x":279,"y":221,"width":222,"height":223,"rx":224,"fill":225,"stroke":226,"strokeWidth":227,"opacity":228},"490",[212,281,283],{"x":282,"y":232,"style":233},"590","wide banner",[212,285,286],{"x":282,"y":237,"style":238},"700px box",[212,288,289],{"x":282,"y":242,"style":243},"6cqi = 42px",[219,291],{"x":292,"y":248,"width":293,"height":249,"rx":250,"fill":251,"opacity":252},"548","84",[212,295,296],{"x":282,"y":255,"style":256},"room for flourish",[212,298,301],{"x":214,"y":299,"style":300},"252","text-anchor:middle;fill:currentColor;font:13px sans-serif;opacity:0.8","the stylesheet says 6cqi once; the box supplies the pixels",[212,303,306],{"x":214,"y":304,"style":305},"282","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.6","no breakpoints, no measurement, no script",[14,308,309],{},"Two independent mechanisms are in play, and keeping them separate is the whole discipline of this section.",[14,311,312,315,316,319,320,323,324,140,327,140,330,140,333,336,337,340],{},[46,313,314],{},"Mechanism one is continuous."," A container query unit is a length that resolves against the query container's dimensions: ",[33,317,318],{},"1cqi"," is one percent of the container's inline size, ",[33,321,322],{},"1cqb"," one percent of its block size. Because it is a length, it is legal everywhere a length is legal — including inside ",[33,325,326],{},"translate()",[33,328,329],{},"translateX()",[33,331,332],{},"margin",[33,334,335],{},"inset",", and keyframe declarations. Writing ",[33,338,339],{},"transform: translateX(6cqi)"," produces a distance that varies smoothly with the box, with no thresholds anywhere. There is no step, no jump, no breakpoint list to maintain.",[14,342,343,346,347,350,351,353,354,356],{},[46,344,345],{},"Mechanism two is discrete."," A size query — ",[33,348,349],{},"@container (min-width: 380px)"," — is a boolean that flips at a threshold, and inside its block you can change anything: which ",[33,352,167],{}," name runs, whether a ",[33,355,163],{}," is declared at all, whether an element is revealed on hover or simply always present. This is the mechanism for decisions that cannot be interpolated. \"Should this panel open on hover, or should its controls just be visible?\" has no halfway answer; it needs a threshold.",[14,358,359],{},"Most real container-aware components use both. The continuous mechanism keeps the ordinary case proportional; the discrete mechanism handles the two or three places where proportionality is not enough and the interaction design itself has to change.",[14,361,362,363,367],{},"The reason this belongs in a motion section rather than a layout one is that motion has a perceptual floor that layout does not. Shrink a font from 18px to 15px and it stays legible. Shrink a slide from 40px to 6px and it stops being a slide — it becomes a shimmer, an artefact, something the eye registers as an error. Layout degrades gracefully under compression; motion degrades into noise. That asymmetry is why a section on container-aware motion needs a page specifically about ",[27,364,366],{"href":365},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers\u002F","suppressing motion in small containers",", and why the honest answer at the bottom of the scale is often zero.",[84,369],{},[87,371,373],{"id":372},"syntax-and-parameters","Syntax and parameters",[375,376,377,393],"table",{},[378,379,380],"thead",{},[381,382,383,387,390],"tr",{},[384,385,386],"th",{},"Token",[384,388,389],{},"Accepted values",[384,391,392],{},"Default \u002F notes",[394,395,396,424,444,464,480,499,515,539],"tbody",{},[381,397,398,404,413],{},[399,400,401],"td",{},[33,402,403],{},"container-type",[399,405,406,140,409,140,411],{},[33,407,408],{},"normal",[33,410,121],{},[33,412,118],{},[399,414,415,417,418,420,421,423],{},[33,416,408],{},". ",[33,419,121],{}," is the safe choice; ",[33,422,118],{}," also contains the block axis and requires an explicit height.",[381,425,426,431,439],{},[399,427,428],{},[33,429,430],{},"container-name",[399,432,433,436,437],{},[33,434,435],{},"\u003Ccustom-ident>"," list, or ",[33,438,225],{},[399,440,441,443],{},[33,442,225],{},". Naming lets a nested descendant target a specific ancestor.",[381,445,446,451,457],{},[399,447,448],{},[33,449,450],{},"container",[399,452,453,456],{},[33,454,455],{},"\u003Cname> \u002F \u003Ctype>"," shorthand",[399,458,459,460,463],{},"Unset. ",[33,461,462],{},"container: card \u002F inline-size"," sets both at once.",[381,465,466,470,473],{},[399,467,468],{},[33,469,318],{},[399,471,472],{},"length",[399,474,475,476,479],{},"1% of the query container's ",[46,477,478],{},"inline"," size — the unit for horizontal travel in a horizontal writing mode.",[381,481,482,486,488],{},[399,483,484],{},[33,485,322],{},[399,487,472],{},[399,489,475,490,493,494,496,497,132],{},[46,491,492],{},"block"," size. Requires ",[33,495,126],{},", not ",[33,498,121],{},[381,500,501,510,512],{},[399,502,503,506,507],{},[33,504,505],{},"1cqmin"," \u002F ",[33,508,509],{},"1cqmax",[399,511,472],{},[399,513,514],{},"1% of the smaller \u002F larger of the two container axes. Useful for square-ish travel that must not overflow either way.",[381,516,517,522,536],{},[399,518,519],{},[33,520,521],{},"@container \u003Cname>? (\u003Ccondition>)",[399,523,524,140,527,140,530,140,533,535],{},[33,525,526],{},"min-width",[33,528,529],{},"max-width",[33,531,532],{},"min-height",[33,534,121],{},", ranges",[399,537,538],{},"Matches against the nearest eligible container, or the named one.",[381,540,541,546,549],{},[399,542,543],{},[33,544,545],{},"@container \u003Cname>? style(--p: v)",[399,547,548],{},"custom property comparison",[399,550,551],{},"Matches on a computed custom property rather than a measurement.",[14,553,554,555,557,558,560,561,563,564,567,568,571,572,575,576,578],{},"Two constraints catch people out. ",[33,556,68],{}," and any block-axis query need ",[33,559,126],{},", which applies containment in both axes and therefore requires the container to have a determinate height — an auto-height container with ",[33,562,126],{}," collapses. And a container query unit used ",[18,565,566],{},"outside"," any container falls back to the small viewport unit equivalent, so ",[33,569,570],{},"6cqi"," on an element with no query-container ancestor silently becomes ",[33,573,574],{},"6svi",", which is why forgetting ",[33,577,403],{}," produces motion that looks plausible but tracks the wrong thing entirely.",[84,580],{},[87,582,584],{"id":583},"step-by-step-implementation","Step-by-step implementation",[586,587,589],"h3",{"id":588},"step-1-establish-the-container-and-take-nothing-else-from-it","Step 1 — Establish the container and take nothing else from it",[14,591,592,593,595,596,132],{},"The wrapper exists to be measured. Give it ",[33,594,403],{}," and, in anything larger than a demo, a name, so a future nested container cannot accidentally intercept the query. Naming conventions are covered in ",[27,597,599],{"href":598},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries\u002F","nesting and naming container queries",[601,602,607],"pre",{"className":603,"code":604,"language":605,"meta":606,"style":606},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast",".card-slot {\n  container: card \u002F inline-size; \u002F* name \u002F type shorthand *\u002F\n}\n","css","",[33,608,609,622,635],{"__ignoreMap":606},[610,611,614,618],"span",{"class":612,"line":613},"line",1,[610,615,617],{"class":616},"s-5SL",".card-slot",[610,619,621],{"class":620},"suds8"," {\n",[610,623,625,628,631],{"class":612,"line":624},2,[610,626,627],{"class":616},"  container",[610,629,630],{"class":620},": card \u002F inline-size; ",[610,632,634],{"class":633},"sLBg1","\u002F* name \u002F type shorthand *\u002F\n",[610,636,638],{"class":612,"line":637},3,[610,639,640],{"class":620},"}\n",[586,642,644],{"id":643},"step-2-express-travel-as-a-container-fraction","Step 2 — Express travel as a container fraction",[14,646,647,648,650],{},"Replace the pixel constant with a ",[33,649,64],{}," value. Pick the number by asking what fraction of the component should move, not how many pixels felt right at one width.",[601,652,654],{"className":603,"code":653,"language":605,"meta":606,"style":606},".card {\n  transform: translateY(0);\n  transition: transform 240ms cubic-bezier(.2, .8, .2, 1);\n}\n\n\u002F* 2% of the container's inline size, upward, on hover. *\u002F\n.card:hover,\n.card:focus-within {\n  transform: translateY(calc(-2cqi));\n}\n",[33,655,656,663,683,722,727,734,740,749,757,781],{"__ignoreMap":606},[610,657,658,661],{"class":612,"line":613},[610,659,660],{"class":616},".card",[610,662,621],{"class":620},[610,664,665,668,671,674,677,680],{"class":612,"line":624},[610,666,667],{"class":616},"  transform",[610,669,670],{"class":620},": ",[610,672,673],{"class":616},"translateY",[610,675,676],{"class":620},"(",[610,678,679],{"class":616},"0",[610,681,682],{"class":620},");\n",[610,684,685,688,691,694,698,701,703,706,708,711,713,715,717,720],{"class":612,"line":637},[610,686,687],{"class":616},"  transition",[610,689,690],{"class":620},": transform ",[610,692,693],{"class":616},"240",[610,695,697],{"class":696},"sHUrx","ms",[610,699,700],{"class":616}," cubic-bezier",[610,702,676],{"class":620},[610,704,705],{"class":616},".2",[610,707,140],{"class":620},[610,709,710],{"class":616},".8",[610,712,140],{"class":620},[610,714,705],{"class":616},[610,716,140],{"class":620},[610,718,719],{"class":616},"1",[610,721,682],{"class":620},[610,723,725],{"class":612,"line":724},4,[610,726,640],{"class":620},[610,728,730],{"class":612,"line":729},5,[610,731,733],{"emptyLinePlaceholder":732},true,"\n",[610,735,737],{"class":612,"line":736},6,[610,738,739],{"class":633},"\u002F* 2% of the container's inline size, upward, on hover. *\u002F\n",[610,741,743,746],{"class":612,"line":742},7,[610,744,745],{"class":616},".card:hover",[610,747,748],{"class":620},",\n",[610,750,752,755],{"class":612,"line":751},8,[610,753,754],{"class":616},".card:focus-within",[610,756,621],{"class":620},[610,758,760,762,764,766,768,771,773,776,778],{"class":612,"line":759},9,[610,761,667],{"class":616},[610,763,670],{"class":620},[610,765,673],{"class":616},[610,767,676],{"class":620},[610,769,770],{"class":616},"calc",[610,772,676],{"class":620},[610,774,775],{"class":616},"-2",[610,777,64],{"class":696},[610,779,780],{"class":620},"));\n",[610,782,784],{"class":612,"line":783},10,[610,785,640],{"class":620},[586,787,789],{"id":788},"step-3-bound-the-fraction-so-extremes-stay-sane","Step 3 — Bound the fraction so extremes stay sane",[14,791,792,793,796,797,800],{},"A raw fraction is unbounded: at 1400px, ",[33,794,795],{},"2cqi"," is 28px, which may be more lift than the design ever wants. ",[33,798,799],{},"clamp()"," gives the proportional value a floor and a ceiling, which is exactly the fluid-sizing pattern applied to distance instead of type.",[601,802,804],{"className":603,"code":803,"language":605,"meta":606,"style":606},".card {\n  \u002F* Never less than 4px of lift, never more than 14px, proportional between. *\u002F\n  --lift: clamp(4px, 2cqi, 14px);\n  transition: transform 240ms cubic-bezier(.2, .8, .2, 1);\n}\n\n.card:hover,\n.card:focus-within { transform: translateY(calc(-1 * var(--lift))); }\n",[33,805,806,812,817,850,880,884,888,894],{"__ignoreMap":606},[610,807,808,810],{"class":612,"line":613},[610,809,660],{"class":616},[610,811,621],{"class":620},[610,813,814],{"class":612,"line":624},[610,815,816],{"class":633},"  \u002F* Never less than 4px of lift, never more than 14px, proportional between. *\u002F\n",[610,818,819,823,825,828,830,832,835,837,840,842,844,846,848],{"class":612,"line":637},[610,820,822],{"class":821},"soyes","  --lift",[610,824,670],{"class":620},[610,826,827],{"class":616},"clamp",[610,829,676],{"class":620},[610,831,250],{"class":616},[610,833,834],{"class":696},"px",[610,836,140],{"class":620},[610,838,839],{"class":616},"2",[610,841,64],{"class":696},[610,843,140],{"class":620},[610,845,249],{"class":616},[610,847,834],{"class":696},[610,849,682],{"class":620},[610,851,852,854,856,858,860,862,864,866,868,870,872,874,876,878],{"class":612,"line":724},[610,853,687],{"class":616},[610,855,690],{"class":620},[610,857,693],{"class":616},[610,859,697],{"class":696},[610,861,700],{"class":616},[610,863,676],{"class":620},[610,865,705],{"class":616},[610,867,140],{"class":620},[610,869,710],{"class":616},[610,871,140],{"class":620},[610,873,705],{"class":616},[610,875,140],{"class":620},[610,877,719],{"class":616},[610,879,682],{"class":620},[610,881,882],{"class":612,"line":729},[610,883,640],{"class":620},[610,885,886],{"class":612,"line":736},[610,887,733],{"emptyLinePlaceholder":732},[610,889,890,892],{"class":612,"line":742},[610,891,745],{"class":616},[610,893,748],{"class":620},[610,895,896,898,901,904,906,908,910,912,914,917,920,923,925,928],{"class":612,"line":751},[610,897,754],{"class":616},[610,899,900],{"class":620}," { ",[610,902,903],{"class":616},"transform",[610,905,670],{"class":620},[610,907,673],{"class":616},[610,909,676],{"class":620},[610,911,770],{"class":616},[610,913,676],{"class":620},[610,915,916],{"class":616},"-1",[610,918,919],{"class":696}," *",[610,921,922],{"class":616}," var",[610,924,676],{"class":620},[610,926,927],{"class":821},"--lift",[610,929,930],{"class":620},"))); }\n",[586,932,934],{"id":933},"step-4-let-pacing-follow-distance","Step 4 — Let pacing follow distance",[14,936,937,938,132],{},"If the distance grows, the duration should grow with it or the wide version reads as faster. Derive a unitless ratio from the container and multiply a base time by it. Keep the ratio dimensionless — a length cannot be multiplied into a ",[33,939,940],{},"\u003Ctime>",[601,942,944],{"className":603,"code":943,"language":605,"meta":606,"style":606},".card {\n  \u002F* Unitless 0.4 … 1 ratio describing how much room the card has.\n     `cqi` is a length, and clamp() cannot mix a length with plain numbers, so the ratio has to\n     be converted first: tan(atan2(\u003Clength>, \u003Clength>)) returns a real \u003Cnumber>. *\u002F\n  --cqi-ratio: tan(atan2(1cqi, 1px));\n  --room: clamp(0.4, calc(var(--cqi-ratio) * 0.16), 1);\n  --lift: clamp(4px, 2cqi, 14px);\n  --beat: calc(120ms + 180ms * var(--room)); \u002F* 120ms … 300ms *\u002F\n\n  transition: transform var(--beat) cubic-bezier(.2, .8, .2, 1);\n}\n",[33,945,946,952,957,962,967,996,1040,1068,1107,1111,1147],{"__ignoreMap":606},[610,947,948,950],{"class":612,"line":613},[610,949,660],{"class":616},[610,951,621],{"class":620},[610,953,954],{"class":612,"line":624},[610,955,956],{"class":633},"  \u002F* Unitless 0.4 … 1 ratio describing how much room the card has.\n",[610,958,959],{"class":612,"line":637},[610,960,961],{"class":633},"     `cqi` is a length, and clamp() cannot mix a length with plain numbers, so the ratio has to\n",[610,963,964],{"class":612,"line":724},[610,965,966],{"class":633},"     be converted first: tan(atan2(\u003Clength>, \u003Clength>)) returns a real \u003Cnumber>. *\u002F\n",[610,968,969,972,974,977,979,982,984,986,988,990,992,994],{"class":612,"line":729},[610,970,971],{"class":821},"  --cqi-ratio",[610,973,670],{"class":620},[610,975,976],{"class":616},"tan",[610,978,676],{"class":620},[610,980,981],{"class":616},"atan2",[610,983,676],{"class":620},[610,985,719],{"class":616},[610,987,64],{"class":696},[610,989,140],{"class":620},[610,991,719],{"class":616},[610,993,834],{"class":696},[610,995,780],{"class":620},[610,997,998,1001,1003,1005,1007,1010,1012,1014,1016,1019,1021,1024,1027,1030,1033,1036,1038],{"class":612,"line":736},[610,999,1000],{"class":821},"  --room",[610,1002,670],{"class":620},[610,1004,827],{"class":616},[610,1006,676],{"class":620},[610,1008,1009],{"class":616},"0.4",[610,1011,140],{"class":620},[610,1013,770],{"class":616},[610,1015,676],{"class":620},[610,1017,1018],{"class":616},"var",[610,1020,676],{"class":620},[610,1022,1023],{"class":821},"--cqi-ratio",[610,1025,1026],{"class":620},") ",[610,1028,1029],{"class":696},"*",[610,1031,1032],{"class":616}," 0.16",[610,1034,1035],{"class":620},"), ",[610,1037,719],{"class":616},[610,1039,682],{"class":620},[610,1041,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1066],{"class":612,"line":742},[610,1043,822],{"class":821},[610,1045,670],{"class":620},[610,1047,827],{"class":616},[610,1049,676],{"class":620},[610,1051,250],{"class":616},[610,1053,834],{"class":696},[610,1055,140],{"class":620},[610,1057,839],{"class":616},[610,1059,64],{"class":696},[610,1061,140],{"class":620},[610,1063,249],{"class":616},[610,1065,834],{"class":696},[610,1067,682],{"class":620},[610,1069,1070,1073,1075,1077,1079,1082,1084,1087,1090,1092,1094,1096,1098,1101,1104],{"class":612,"line":751},[610,1071,1072],{"class":821},"  --beat",[610,1074,670],{"class":620},[610,1076,770],{"class":616},[610,1078,676],{"class":620},[610,1080,1081],{"class":616},"120",[610,1083,697],{"class":696},[610,1085,1086],{"class":696}," +",[610,1088,1089],{"class":616}," 180",[610,1091,697],{"class":696},[610,1093,919],{"class":696},[610,1095,922],{"class":616},[610,1097,676],{"class":620},[610,1099,1100],{"class":821},"--room",[610,1102,1103],{"class":620},")); ",[610,1105,1106],{"class":633},"\u002F* 120ms … 300ms *\u002F\n",[610,1108,1109],{"class":612,"line":759},[610,1110,733],{"emptyLinePlaceholder":732},[610,1112,1113,1115,1117,1119,1121,1124,1126,1129,1131,1133,1135,1137,1139,1141,1143,1145],{"class":612,"line":783},[610,1114,687],{"class":616},[610,1116,690],{"class":620},[610,1118,1018],{"class":616},[610,1120,676],{"class":620},[610,1122,1123],{"class":821},"--beat",[610,1125,1026],{"class":620},[610,1127,1128],{"class":616},"cubic-bezier",[610,1130,676],{"class":620},[610,1132,705],{"class":616},[610,1134,140],{"class":620},[610,1136,710],{"class":616},[610,1138,140],{"class":620},[610,1140,705],{"class":616},[610,1142,140],{"class":620},[610,1144,719],{"class":616},[610,1146,682],{"class":620},[610,1148,1150],{"class":612,"line":1149},11,[610,1151,640],{"class":620},[14,1153,1154,1155,1158],{},"Drag the frame below and hover at each width — the card rises further ",[18,1156,1157],{},"and"," takes longer as the container grows, so the perceived velocity stays constant.",[1160,1161],"live-demo",{"name":1162},"cmotion-proportional-card",[586,1164,1166],{"id":1165},"step-5-add-the-discrete-decisions-on-top","Step 5 — Add the discrete decisions on top",[14,1168,1169],{},"Continuous scaling handles the middle of the range. At the ends, use a query. Here the narrowest containers drop the lift entirely, because a 4px hover translate on a 240px card is imperceptible at best and jittery at worst.",[601,1171,1173],{"className":603,"code":1172,"language":605,"meta":606,"style":606},"@container card (max-width: 300px) {\n  .card { transition: none; }\n  .card:hover,\n  .card:focus-within { transform: none; box-shadow: 0 0 0 1px currentColor; }\n}\n",[33,1174,1175,1182,1198,1205,1243],{"__ignoreMap":606},[610,1176,1177,1179],{"class":612,"line":613},[610,1178,35],{"class":696},[610,1180,1181],{"class":620}," card (max-width: 300px) {\n",[610,1183,1184,1187,1189,1191,1193,1195],{"class":612,"line":624},[610,1185,1186],{"class":616},"  .card",[610,1188,900],{"class":620},[610,1190,163],{"class":616},[610,1192,670],{"class":620},[610,1194,225],{"class":616},[610,1196,1197],{"class":620},"; }\n",[610,1199,1200,1203],{"class":612,"line":637},[610,1201,1202],{"class":616},"  .card:hover",[610,1204,748],{"class":620},[610,1206,1207,1210,1212,1214,1216,1218,1221,1224,1226,1228,1231,1233,1236,1238,1241],{"class":612,"line":724},[610,1208,1209],{"class":616},"  .card:focus-within",[610,1211,900],{"class":620},[610,1213,903],{"class":616},[610,1215,670],{"class":620},[610,1217,225],{"class":616},[610,1219,1220],{"class":620},"; ",[610,1222,1223],{"class":616},"box-shadow",[610,1225,670],{"class":620},[610,1227,679],{"class":616},[610,1229,1230],{"class":616}," 0",[610,1232,1230],{"class":616},[610,1234,1235],{"class":616}," 1",[610,1237,834],{"class":696},[610,1239,1240],{"class":616}," currentColor",[610,1242,1197],{"class":620},[610,1244,1245],{"class":612,"line":729},[610,1246,640],{"class":620},[14,1248,1249,1250,1253],{},"Note that the narrow case still ",[18,1251,1252],{},"responds"," to hover — it just responds with a static change rather than a movement. Removing the movement and removing the feedback are different things, and confusing them is how reduced variants end up feeling broken.",[586,1255,1257],{"id":1256},"step-6-put-the-user-preference-above-everything","Step 6 — Put the user preference above everything",[14,1259,1260],{},"Container size decides what motion is appropriate. It never decides whether motion is allowed. The preference query goes last and overrides both branches.",[601,1262,1264],{"className":603,"code":1263,"language":605,"meta":606,"style":606},"@media (prefers-reduced-motion: reduce) {\n  .card,\n  .card:hover,\n  .card:focus-within {\n    transition: none;\n    transform: none;\n  }\n}\n",[33,1265,1266,1274,1280,1286,1292,1304,1315,1320],{"__ignoreMap":606},[610,1267,1268,1271],{"class":612,"line":613},[610,1269,1270],{"class":696},"@media",[610,1272,1273],{"class":620}," (prefers-reduced-motion: reduce) {\n",[610,1275,1276,1278],{"class":612,"line":624},[610,1277,1186],{"class":616},[610,1279,748],{"class":620},[610,1281,1282,1284],{"class":612,"line":637},[610,1283,1202],{"class":616},[610,1285,748],{"class":620},[610,1287,1288,1290],{"class":612,"line":724},[610,1289,1209],{"class":616},[610,1291,621],{"class":620},[610,1293,1294,1297,1299,1301],{"class":612,"line":729},[610,1295,1296],{"class":616},"    transition",[610,1298,670],{"class":620},[610,1300,225],{"class":616},[610,1302,1303],{"class":620},";\n",[610,1305,1306,1309,1311,1313],{"class":612,"line":736},[610,1307,1308],{"class":616},"    transform",[610,1310,670],{"class":620},[610,1312,225],{"class":616},[610,1314,1303],{"class":620},[610,1316,1317],{"class":612,"line":742},[610,1318,1319],{"class":620},"  }\n",[610,1321,1322],{"class":612,"line":751},[610,1323,640],{"class":620},[84,1325],{},[87,1327,1329],{"id":1328},"annotated-production-example-a-queue-item-that-changes-its-own-affordance","Annotated production example: a queue item that changes its own affordance",[14,1331,1332],{},"This is a realistic list row — the kind that appears in a wide inbox pane, a medium two-column dashboard, and a narrow mobile-width rail, from the same markup. Above 380px of container width it hides its actions and slides them open on hover or focus. Below that, the actions are simply always there, because hover-to-reveal has no touch equivalent and no room to expand into.",[1160,1334],{"name":1335},"cmotion-affordance-swap",[601,1337,1341],{"className":1338,"code":1339,"language":1340,"meta":606,"style":606},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cdiv class=\"holder\">\n  \u003Carticle class=\"item\">\n    \u003Ch3 class=\"item__name\">Northwind invoice #4192\u003C\u002Fh3>\n    \u003Cp class=\"item__meta\">Due 14 August &middot; 2 attachments\u003C\u002Fp>\n    \u003Cdiv class=\"item__extra\">\n      \u003Ca class=\"item__act\" href=\"#\">Approve\u003C\u002Fa>\n      \u003Ca class=\"item__act\" href=\"#\">Request change\u003C\u002Fa>\n    \u003C\u002Fdiv>\n  \u003C\u002Farticle>\n\u003C\u002Fdiv>\n","html",[33,1342,1343,1365,1382,1403,1429,1444,1473,1498,1507,1516],{"__ignoreMap":606},[610,1344,1345,1348,1352,1355,1358,1362],{"class":612,"line":613},[610,1346,1347],{"class":620},"\u003C",[610,1349,1351],{"class":1350},"sne4z","div",[610,1353,1354],{"class":616}," class",[610,1356,1357],{"class":620},"=",[610,1359,1361],{"class":1360},"sT6z2","\"holder\"",[610,1363,1364],{"class":620},">\n",[610,1366,1367,1370,1373,1375,1377,1380],{"class":612,"line":624},[610,1368,1369],{"class":620},"  \u003C",[610,1371,1372],{"class":1350},"article",[610,1374,1354],{"class":616},[610,1376,1357],{"class":620},[610,1378,1379],{"class":1360},"\"item\"",[610,1381,1364],{"class":620},[610,1383,1384,1387,1389,1391,1393,1396,1399,1401],{"class":612,"line":637},[610,1385,1386],{"class":620},"    \u003C",[610,1388,586],{"class":1350},[610,1390,1354],{"class":616},[610,1392,1357],{"class":620},[610,1394,1395],{"class":1360},"\"item__name\"",[610,1397,1398],{"class":620},">Northwind invoice #4192\u003C\u002F",[610,1400,586],{"class":1350},[610,1402,1364],{"class":620},[610,1404,1405,1407,1409,1411,1413,1416,1419,1422,1425,1427],{"class":612,"line":724},[610,1406,1386],{"class":620},[610,1408,14],{"class":1350},[610,1410,1354],{"class":616},[610,1412,1357],{"class":620},[610,1414,1415],{"class":1360},"\"item__meta\"",[610,1417,1418],{"class":620},">Due 14 August ",[610,1420,1421],{"class":696},"&middot;",[610,1423,1424],{"class":620}," 2 attachments\u003C\u002F",[610,1426,14],{"class":1350},[610,1428,1364],{"class":620},[610,1430,1431,1433,1435,1437,1439,1442],{"class":612,"line":729},[610,1432,1386],{"class":620},[610,1434,1351],{"class":1350},[610,1436,1354],{"class":616},[610,1438,1357],{"class":620},[610,1440,1441],{"class":1360},"\"item__extra\"",[610,1443,1364],{"class":620},[610,1445,1446,1449,1451,1453,1455,1458,1461,1463,1466,1469,1471],{"class":612,"line":736},[610,1447,1448],{"class":620},"      \u003C",[610,1450,27],{"class":1350},[610,1452,1354],{"class":616},[610,1454,1357],{"class":620},[610,1456,1457],{"class":1360},"\"item__act\"",[610,1459,1460],{"class":616}," href",[610,1462,1357],{"class":620},[610,1464,1465],{"class":1360},"\"#\"",[610,1467,1468],{"class":620},">Approve\u003C\u002F",[610,1470,27],{"class":1350},[610,1472,1364],{"class":620},[610,1474,1475,1477,1479,1481,1483,1485,1487,1489,1491,1494,1496],{"class":612,"line":742},[610,1476,1448],{"class":620},[610,1478,27],{"class":1350},[610,1480,1354],{"class":616},[610,1482,1357],{"class":620},[610,1484,1457],{"class":1360},[610,1486,1460],{"class":616},[610,1488,1357],{"class":620},[610,1490,1465],{"class":1360},[610,1492,1493],{"class":620},">Request change\u003C\u002F",[610,1495,27],{"class":1350},[610,1497,1364],{"class":620},[610,1499,1500,1503,1505],{"class":612,"line":751},[610,1501,1502],{"class":620},"    \u003C\u002F",[610,1504,1351],{"class":1350},[610,1506,1364],{"class":620},[610,1508,1509,1512,1514],{"class":612,"line":759},[610,1510,1511],{"class":620},"  \u003C\u002F",[610,1513,1372],{"class":1350},[610,1515,1364],{"class":620},[610,1517,1518,1521,1523],{"class":612,"line":783},[610,1519,1520],{"class":620},"\u003C\u002F",[610,1522,1351],{"class":1350},[610,1524,1364],{"class":620},[601,1526,1528],{"className":603,"code":1527,"language":605,"meta":606,"style":606},".holder { container-type: inline-size; container-name: holder; }\n\n.item {\n  padding: 1rem;\n  border: 1px solid var(--demo-border);\n  border-radius: 12px;\n  background: var(--demo-surface);\n}\n.item__name { margin: 0 0 .25rem; font-size: 1rem; color: var(--demo-fg); }\n.item__meta { margin: 0; color: var(--demo-muted); font-size: .85rem; }\n\n\u002F* Narrow default: the actions are simply part of the card, always reachable. *\u002F\n.item__extra {\n  display: flex;\n  gap: .5rem;\n  flex-wrap: wrap;\n  margin-top: .75rem;\n}\n\n.item__act {\n  padding: .4rem .7rem;\n  border: 1px solid var(--demo-accent);\n  border-radius: 999px;\n  color: var(--demo-accent);\n  text-decoration: none;\n  font-size: .82rem;\n}\n\n\u002F* Only when there is room does the reveal affordance switch on. *\u002F\n@container holder (min-width: 380px) {\n  .item__extra {\n    margin-top: 0;\n    max-height: 0;\n    opacity: 0;\n    overflow: hidden;\n    transition: max-height .3s ease, opacity .3s ease, margin-top .3s ease;\n  }\n  .item:hover .item__extra,\n  .item:focus-within .item__extra {\n    max-height: 4rem;\n    opacity: 1;\n    margin-top: .75rem;\n  }\n}\n",[33,1529,1530,1547,1551,1558,1572,1595,1608,1624,1628,1676,1716,1720,1726,1734,1747,1762,1775,1790,1795,1800,1808,1827,1849,1863,1879,1891,1906,1911,1916,1922,1930,1938,1950,1962,1974,1987,2024,2029,2040,2050,2063,2074,2087,2092],{"__ignoreMap":606},[610,1531,1532,1535,1537,1539,1542,1544],{"class":612,"line":613},[610,1533,1534],{"class":616},".holder",[610,1536,900],{"class":620},[610,1538,403],{"class":616},[610,1540,1541],{"class":620},": inline-size; ",[610,1543,430],{"class":616},[610,1545,1546],{"class":620},": holder; }\n",[610,1548,1549],{"class":612,"line":624},[610,1550,733],{"emptyLinePlaceholder":732},[610,1552,1553,1556],{"class":612,"line":637},[610,1554,1555],{"class":616},".item",[610,1557,621],{"class":620},[610,1559,1560,1563,1565,1567,1570],{"class":612,"line":724},[610,1561,1562],{"class":616},"  padding",[610,1564,670],{"class":620},[610,1566,719],{"class":616},[610,1568,1569],{"class":696},"rem",[610,1571,1303],{"class":620},[610,1573,1574,1577,1579,1581,1583,1586,1588,1590,1593],{"class":612,"line":729},[610,1575,1576],{"class":616},"  border",[610,1578,670],{"class":620},[610,1580,719],{"class":616},[610,1582,834],{"class":696},[610,1584,1585],{"class":616}," solid",[610,1587,922],{"class":616},[610,1589,676],{"class":620},[610,1591,1592],{"class":821},"--demo-border",[610,1594,682],{"class":620},[610,1596,1597,1600,1602,1604,1606],{"class":612,"line":736},[610,1598,1599],{"class":616},"  border-radius",[610,1601,670],{"class":620},[610,1603,224],{"class":616},[610,1605,834],{"class":696},[610,1607,1303],{"class":620},[610,1609,1610,1613,1615,1617,1619,1622],{"class":612,"line":742},[610,1611,1612],{"class":616},"  background",[610,1614,670],{"class":620},[610,1616,1018],{"class":616},[610,1618,676],{"class":620},[610,1620,1621],{"class":821},"--demo-surface",[610,1623,682],{"class":620},[610,1625,1626],{"class":612,"line":751},[610,1627,640],{"class":620},[610,1629,1630,1633,1635,1637,1639,1641,1643,1646,1648,1650,1653,1655,1657,1659,1661,1664,1666,1668,1670,1673],{"class":612,"line":759},[610,1631,1632],{"class":616},".item__name",[610,1634,900],{"class":620},[610,1636,332],{"class":616},[610,1638,670],{"class":620},[610,1640,679],{"class":616},[610,1642,1230],{"class":616},[610,1644,1645],{"class":616}," .25",[610,1647,1569],{"class":696},[610,1649,1220],{"class":620},[610,1651,1652],{"class":616},"font-size",[610,1654,670],{"class":620},[610,1656,719],{"class":616},[610,1658,1569],{"class":696},[610,1660,1220],{"class":620},[610,1662,1663],{"class":616},"color",[610,1665,670],{"class":620},[610,1667,1018],{"class":616},[610,1669,676],{"class":620},[610,1671,1672],{"class":821},"--demo-fg",[610,1674,1675],{"class":620},"); }\n",[610,1677,1678,1681,1683,1685,1687,1689,1691,1693,1695,1697,1699,1702,1705,1707,1709,1712,1714],{"class":612,"line":783},[610,1679,1680],{"class":616},".item__meta",[610,1682,900],{"class":620},[610,1684,332],{"class":616},[610,1686,670],{"class":620},[610,1688,679],{"class":616},[610,1690,1220],{"class":620},[610,1692,1663],{"class":616},[610,1694,670],{"class":620},[610,1696,1018],{"class":616},[610,1698,676],{"class":620},[610,1700,1701],{"class":821},"--demo-muted",[610,1703,1704],{"class":620},"); ",[610,1706,1652],{"class":616},[610,1708,670],{"class":620},[610,1710,1711],{"class":616},".85",[610,1713,1569],{"class":696},[610,1715,1197],{"class":620},[610,1717,1718],{"class":612,"line":1149},[610,1719,733],{"emptyLinePlaceholder":732},[610,1721,1723],{"class":612,"line":1722},12,[610,1724,1725],{"class":633},"\u002F* Narrow default: the actions are simply part of the card, always reachable. *\u002F\n",[610,1727,1729,1732],{"class":612,"line":1728},13,[610,1730,1731],{"class":616},".item__extra",[610,1733,621],{"class":620},[610,1735,1737,1740,1742,1745],{"class":612,"line":1736},14,[610,1738,1739],{"class":616},"  display",[610,1741,670],{"class":620},[610,1743,1744],{"class":616},"flex",[610,1746,1303],{"class":620},[610,1748,1750,1753,1755,1758,1760],{"class":612,"line":1749},15,[610,1751,1752],{"class":616},"  gap",[610,1754,670],{"class":620},[610,1756,1757],{"class":616},".5",[610,1759,1569],{"class":696},[610,1761,1303],{"class":620},[610,1763,1765,1768,1770,1773],{"class":612,"line":1764},16,[610,1766,1767],{"class":616},"  flex-wrap",[610,1769,670],{"class":620},[610,1771,1772],{"class":616},"wrap",[610,1774,1303],{"class":620},[610,1776,1778,1781,1783,1786,1788],{"class":612,"line":1777},17,[610,1779,1780],{"class":616},"  margin-top",[610,1782,670],{"class":620},[610,1784,1785],{"class":616},".75",[610,1787,1569],{"class":696},[610,1789,1303],{"class":620},[610,1791,1793],{"class":612,"line":1792},18,[610,1794,640],{"class":620},[610,1796,1798],{"class":612,"line":1797},19,[610,1799,733],{"emptyLinePlaceholder":732},[610,1801,1803,1806],{"class":612,"line":1802},20,[610,1804,1805],{"class":616},".item__act",[610,1807,621],{"class":620},[610,1809,1811,1813,1815,1818,1820,1823,1825],{"class":612,"line":1810},21,[610,1812,1562],{"class":616},[610,1814,670],{"class":620},[610,1816,1817],{"class":616},".4",[610,1819,1569],{"class":696},[610,1821,1822],{"class":616}," .7",[610,1824,1569],{"class":696},[610,1826,1303],{"class":620},[610,1828,1830,1832,1834,1836,1838,1840,1842,1844,1847],{"class":612,"line":1829},22,[610,1831,1576],{"class":616},[610,1833,670],{"class":620},[610,1835,719],{"class":616},[610,1837,834],{"class":696},[610,1839,1585],{"class":616},[610,1841,922],{"class":616},[610,1843,676],{"class":620},[610,1845,1846],{"class":821},"--demo-accent",[610,1848,682],{"class":620},[610,1850,1852,1854,1856,1859,1861],{"class":612,"line":1851},23,[610,1853,1599],{"class":616},[610,1855,670],{"class":620},[610,1857,1858],{"class":616},"999",[610,1860,834],{"class":696},[610,1862,1303],{"class":620},[610,1864,1866,1869,1871,1873,1875,1877],{"class":612,"line":1865},24,[610,1867,1868],{"class":616},"  color",[610,1870,670],{"class":620},[610,1872,1018],{"class":616},[610,1874,676],{"class":620},[610,1876,1846],{"class":821},[610,1878,682],{"class":620},[610,1880,1882,1885,1887,1889],{"class":612,"line":1881},25,[610,1883,1884],{"class":616},"  text-decoration",[610,1886,670],{"class":620},[610,1888,225],{"class":616},[610,1890,1303],{"class":620},[610,1892,1894,1897,1899,1902,1904],{"class":612,"line":1893},26,[610,1895,1896],{"class":616},"  font-size",[610,1898,670],{"class":620},[610,1900,1901],{"class":616},".82",[610,1903,1569],{"class":696},[610,1905,1303],{"class":620},[610,1907,1909],{"class":612,"line":1908},27,[610,1910,640],{"class":620},[610,1912,1914],{"class":612,"line":1913},28,[610,1915,733],{"emptyLinePlaceholder":732},[610,1917,1919],{"class":612,"line":1918},29,[610,1920,1921],{"class":633},"\u002F* Only when there is room does the reveal affordance switch on. *\u002F\n",[610,1923,1925,1927],{"class":612,"line":1924},30,[610,1926,35],{"class":696},[610,1928,1929],{"class":620}," holder (min-width: 380px) {\n",[610,1931,1933,1936],{"class":612,"line":1932},31,[610,1934,1935],{"class":616},"  .item__extra",[610,1937,621],{"class":620},[610,1939,1941,1944,1946,1948],{"class":612,"line":1940},32,[610,1942,1943],{"class":616},"    margin-top",[610,1945,670],{"class":620},[610,1947,679],{"class":616},[610,1949,1303],{"class":620},[610,1951,1953,1956,1958,1960],{"class":612,"line":1952},33,[610,1954,1955],{"class":616},"    max-height",[610,1957,670],{"class":620},[610,1959,679],{"class":616},[610,1961,1303],{"class":620},[610,1963,1965,1968,1970,1972],{"class":612,"line":1964},34,[610,1966,1967],{"class":616},"    opacity",[610,1969,670],{"class":620},[610,1971,679],{"class":616},[610,1973,1303],{"class":620},[610,1975,1977,1980,1982,1985],{"class":612,"line":1976},35,[610,1978,1979],{"class":616},"    overflow",[610,1981,670],{"class":620},[610,1983,1984],{"class":616},"hidden",[610,1986,1303],{"class":620},[610,1988,1990,1992,1995,1998,2001,2004,2007,2009,2011,2013,2016,2018,2020,2022],{"class":612,"line":1989},36,[610,1991,1296],{"class":616},[610,1993,1994],{"class":620},": max-height ",[610,1996,1997],{"class":616},".3",[610,1999,2000],{"class":696},"s",[610,2002,2003],{"class":616}," ease",[610,2005,2006],{"class":620},", opacity ",[610,2008,1997],{"class":616},[610,2010,2000],{"class":696},[610,2012,2003],{"class":616},[610,2014,2015],{"class":620},", margin-top ",[610,2017,1997],{"class":616},[610,2019,2000],{"class":696},[610,2021,2003],{"class":616},[610,2023,1303],{"class":620},[610,2025,2027],{"class":612,"line":2026},37,[610,2028,1319],{"class":620},[610,2030,2032,2035,2038],{"class":612,"line":2031},38,[610,2033,2034],{"class":616},"  .item:hover",[610,2036,2037],{"class":616}," .item__extra",[610,2039,748],{"class":620},[610,2041,2043,2046,2048],{"class":612,"line":2042},39,[610,2044,2045],{"class":616},"  .item:focus-within",[610,2047,2037],{"class":616},[610,2049,621],{"class":620},[610,2051,2053,2055,2057,2059,2061],{"class":612,"line":2052},40,[610,2054,1955],{"class":616},[610,2056,670],{"class":620},[610,2058,250],{"class":616},[610,2060,1569],{"class":696},[610,2062,1303],{"class":620},[610,2064,2066,2068,2070,2072],{"class":612,"line":2065},41,[610,2067,1967],{"class":616},[610,2069,670],{"class":620},[610,2071,719],{"class":616},[610,2073,1303],{"class":620},[610,2075,2077,2079,2081,2083,2085],{"class":612,"line":2076},42,[610,2078,1943],{"class":616},[610,2080,670],{"class":620},[610,2082,1785],{"class":616},[610,2084,1569],{"class":696},[610,2086,1303],{"class":620},[610,2088,2090],{"class":612,"line":2089},43,[610,2091,1319],{"class":620},[610,2093,2095],{"class":612,"line":2094},44,[610,2096,640],{"class":620},[2098,2099,2100],"blockquote",{},[14,2101,2102,2103,2106],{},"The ",[33,2104,2105],{},"--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,2108,2109,2110,2113,2114,2117,2118,2121,2122,2125],{},"Three details are load-bearing. First, the ",[18,2111,2112],{},"default"," is the always-visible variant and the reveal is the enhancement — written the other way round, an engine without container query support would ship a permanently hidden action row, which is a functional regression rather than a cosmetic one. Second, ",[33,2115,2116],{},":focus-within"," accompanies ",[33,2119,2120],{},":hover"," on every reveal rule, so a keyboard user tabbing into a hidden action opens the panel; without it the focused control sits inside a zero-height overflow-hidden box and the focus ring is invisible. Third, the transition is declared ",[18,2123,2124],{},"inside"," the query, not outside — so the narrow variant has no transition property to accidentally animate when the container resizes across the threshold.",[14,2127,2128,2129,2132,2133,2137,2138,132],{},"The interaction-design argument behind this pattern, including why ",[33,2130,2131],{},"hover: none"," pointer detection is a complement rather than a substitute, is developed in ",[27,2134,2136],{"href":2135},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances\u002F","container query hover affordances",". For the layout side of the same component — how the card itself reflows across widths — see ",[27,2139,2141],{"href":2140},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fbuilding-responsive-cards-with-container-queries\u002F","building responsive cards with container queries",[84,2143],{},[87,2145,2147],{"id":2146},"performance-and-accessibility-notes","Performance and accessibility notes",[14,2149,2150,2153,2154,2156,2157,2159,2160,2163,2164,132],{},[46,2151,2152],{},"Container units are free at animation time."," A ",[33,2155,64],{}," value is resolved during style computation into an absolute length; by the time the compositor has the transform, it is looking at pixels like any other. Animating ",[33,2158,339],{}," therefore stays on the compositor thread exactly as ",[33,2161,2162],{},"translateX(24px)"," would, and the same guidance about which properties are cheap applies unchanged — see ",[27,2165,2167],{"href":2166},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fwill-change-and-the-compositor-thread\u002F","will-change and the compositor thread",[14,2169,2170,2173,2174,2176,2177,2179],{},[46,2171,2172],{},"The cost shows up on resize, not on play."," When a query container changes size, the browser must re-resolve every container unit inside it and re-evaluate every ",[33,2175,35],{}," condition that targets it. That is style work proportional to the subtree, and it is why you should not nest twelve query containers inside each other for the sake of it, and why ",[33,2178,126],{}," is worth avoiding unless you genuinely need the block axis. During a drag-resize or a sidebar collapse animation, that recomputation happens every frame.",[14,2181,2182,2187,2188,2190],{},[46,2183,2184,2185,132],{},"Do not animate the container's own size while its children read ",[33,2186,64],{}," Animating the width of a query container makes every descendant's container-unit length a moving target, which forces layout and style recalculation on every frame and produces exactly the jank the compositor was avoiding. Animate the container's ",[33,2189,903],{}," instead, or animate the children and leave the box still.",[14,2192,2193,2199],{},[46,2194,2195,2198],{},[33,2196,2197],{},"will-change"," is still a scarce resource."," Container awareness does not change the rule: add it to the handful of elements actively animating, remove it when they stop, and never blanket-apply it to a list.",[14,2201,2202,2205,2206,2210,2211,2213,2214,2217,2218,132],{},[46,2203,2204],{},"Accessibility comes in three parts."," Reduced-motion handling must sit outside the container logic and win over it — that is non-negotiable, and the recipes in ",[27,2207,2209],{"href":2208},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes\u002F","prefers-reduced-motion recipes"," apply as written. Any hover-revealed content must be equally reachable by keyboard via ",[33,2212,2116],{},", and must not be the ",[18,2215,2216],{},"only"," route to a function. And large-amplitude movement is a vestibular concern independent of container size — a wide container is permission to move more, not permission to move a lot; the boundaries are covered in ",[27,2219,2221],{"href":2220},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns\u002F","vestibular-safe animation patterns",[84,2223],{},[87,2225,2227],{"id":2226},"devtools-debugging-workflow","DevTools debugging workflow",[14,2229,2230],{},"Container-aware motion fails in ways that look like nothing happening, so the debugging loop is mostly about confirming which container is answering.",[2232,2233,2234,2246,2256,2268,2285,2295],"ol",{},[59,2235,2236,2239,2240,2242,2243,2245],{},[46,2237,2238],{},"Confirm a container exists."," In Chrome or Edge DevTools, select the animating element and look at the Elements panel — an ancestor acting as a query container is badged ",[33,2241,450],{},". If no ancestor carries the badge, your ",[33,2244,64],{}," values are silently resolving against the viewport.",[59,2247,2248,2251,2252,2255],{},[46,2249,2250],{},"Check the Computed pane, not the Styles pane."," The Styles pane shows ",[33,2253,2254],{},"translateY(-2cqi)"," as authored. The Computed pane shows the resolved pixel length. If Computed reports a value that tracks the window rather than the box as you resize, containment is on the wrong ancestor.",[59,2257,2258,2264,2265,2267],{},[46,2259,2260,2261,2263],{},"Watch the ",[33,2262,35],{}," rule flip live."," With the element selected, drag the window or the container's own size in the layout; matching ",[33,2266,35],{}," blocks appear and disappear from the Styles pane in real time. A rule that never appears has a name mismatch or is querying an axis the container does not contain.",[59,2269,2270,2273,2274,2277,2278,2280,2281,2284],{},[46,2271,2272],{},"Use the Animations panel to check duration, not distance."," Open the Animations drawer, trigger the interaction, and read the actual duration. If a ",[33,2275,2276],{},"calc()"," produced an invalid ",[33,2279,940],{}," — the classic being multiplying a length by a time — the declaration is dropped and the element falls back to the initial ",[33,2282,2283],{},"0s",", which looks identical to \"no transition declared\".",[59,2286,2287,2290,2291,2294],{},[46,2288,2289],{},"Toggle reduced motion from the Rendering drawer."," Emulate ",[33,2292,2293],{},"prefers-reduced-motion: reduce"," and re-run every container width. The reduced variant must still show a visible state change on hover and focus at every size.",[59,2296,2297,2300],{},[46,2298,2299],{},"Watch the Performance timeline while resizing."," A resize that triggers a long purple style-recalculation bar in a component using many container units is the signal to reduce the number of nested containers or to stop animating the container's dimensions.",[84,2302],{},[87,2304,2306],{"id":2305},"browser-compatibility","Browser compatibility",[375,2308,2309,2325],{},[378,2310,2311],{},[381,2312,2313,2316,2319,2322],{},[384,2314,2315],{},"Feature",[384,2317,2318],{},"Chrome \u002F Edge",[384,2320,2321],{},"Safari",[384,2323,2324],{},"Firefox",[394,2326,2327,2346,2365,2380,2394,2410],{},[381,2328,2329,2337,2340,2343],{},[399,2330,2331,2332,140,2334,2336],{},"Size container queries (",[33,2333,35],{},[33,2335,403],{},")",[399,2338,2339],{},"105+",[399,2341,2342],{},"16+",[399,2344,2345],{},"110+",[381,2347,2348,2359,2361,2363],{},[399,2349,2350,2351,140,2353,140,2355,140,2357,2336],{},"Container query units (",[33,2352,64],{},[33,2354,68],{},[33,2356,145],{},[33,2358,149],{},[399,2360,2339],{},[399,2362,2342],{},[399,2364,2345],{},[381,2366,2367,2374,2376,2378],{},[399,2368,2369,2370,506,2372],{},"Container units inside ",[33,2371,903],{},[33,2373,167],{},[399,2375,2339],{},[399,2377,2342],{},[399,2379,2345],{},[381,2381,2382,2385,2388,2391],{},[399,2383,2384],{},"Style queries for custom properties",[399,2386,2387],{},"111+",[399,2389,2390],{},"18+",[399,2392,2393],{},"not yet",[381,2395,2396,2401,2404,2407],{},[399,2397,2398,2400],{},[33,2399,799],{}," in length and ratio arithmetic",[399,2402,2403],{},"79+",[399,2405,2406],{},"13.1+",[399,2408,2409],{},"75+",[381,2411,2412,2416,2419,2422],{},[399,2413,2414],{},[33,2415,179],{},[399,2417,2418],{},"74+",[399,2420,2421],{},"10.1+",[399,2423,2424],{},"63+",[14,2426,2427,2428,2430,2431,2434,2435,2439,2440,2444],{},"Everything in the continuous half of this section — ",[33,2429,64],{}," distances, clamped travel, derived durations — has been interoperable since early 2023. Style queries are the one piece still missing an implementation in Firefox, so treat any style-query-driven motion switch as an enhancement layered over a size-query or class-based default. Where you need to gate the whole approach, ",[33,2432,2433],{},"@supports (container-type: inline-size)"," is the correct test; the pattern is set out in ",[27,2436,2438],{"href":2437},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports\u002F","feature detection with @supports",", and the viewport-breakpoint fallbacks in ",[27,2441,2443],{"href":2442},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers\u002F","handling container query fallbacks for older browsers"," still apply to motion exactly as they do to layout.",[84,2446],{},[87,2448,2450],{"id":2449},"common-pitfalls","Common pitfalls",[375,2452,2453,2466],{},[378,2454,2455],{},[381,2456,2457,2460,2463],{},[384,2458,2459],{},"Pitfall",[384,2461,2462],{},"Cause",[384,2464,2465],{},"Resolution",[394,2467,2468,2490,2512,2528,2552],{},[381,2469,2470,2475,2481],{},[399,2471,2472,2474],{},[33,2473,64],{}," distances track the window, not the component",[399,2476,2477,2478,2480],{},"No ancestor has ",[33,2479,403],{},", so container units fall back to viewport units",[399,2482,2483,2484,2486,2487,2489],{},"Add ",[33,2485,104],{}," to the wrapper and confirm the ",[33,2488,450],{}," badge in DevTools",[381,2491,2492,2495,2500],{},[399,2493,2494],{},"The container collapses to zero height",[399,2496,2497,2499],{},[33,2498,126],{}," applies block-axis containment to an auto-height box",[399,2501,2502,2503,2505,2506,2508,2509,2511],{},"Use ",[33,2504,121],{}," unless you need ",[33,2507,68],{},"; if you need ",[33,2510,68],{},", give the container a determinate height",[381,2513,2514,2517,2525],{},[399,2515,2516],{},"A derived duration is ignored entirely",[399,2518,2519,2521,2522,2524],{},[33,2520,2276],{}," multiplied a length by a time, producing an invalid ",[33,2523,940],{}," that the parser drops",[399,2526,2527],{},"Reduce the container value to a unitless ratio first, then multiply the base time by it",[381,2529,2530,2533,2543],{},[399,2531,2532],{},"Hover reveal traps keyboard focus in an invisible box",[399,2534,2535,2536,2538,2539,2542],{},"The reveal rule matches ",[33,2537,2120],{}," only, while ",[33,2540,2541],{},"overflow: hidden"," clips the focused control",[399,2544,2545,2546,2548,2549,2551],{},"Pair every ",[33,2547,2120],{}," reveal with ",[33,2550,2116],{}," on the same selector list",[381,2553,2554,2557,2560],{},[399,2555,2556],{},"Motion re-plays or stutters while the sidebar animates open",[399,2558,2559],{},"The query container's own width is being animated, forcing style and layout recalculation each frame",[399,2561,2562,2563,2565],{},"Animate a ",[33,2564,903],{}," on the container instead of its width, or suspend descendant transitions during the resize",[84,2567],{},[87,2569,2571],{"id":2570},"faq","FAQ",[14,2573,2574,2577,2578,2580],{},[46,2575,2576],{},"What makes motion container-aware rather than responsive?","\nResponsive motion changes with the viewport, so a component sitting in a narrow sidebar on a large screen still gets desktop-sized movement. Container-aware motion measures the element's own containing box with ",[33,2579,35],{}," and container query units, so the same component moves less in a narrow slot and more in a wide one.",[14,2582,2583,2586,2587,2590,2591,2594,2595,2597,2598,2600,2601,132],{},[46,2584,2585],{},"Can I use cqi directly inside transform and keyframes?","\nYes. Container query units resolve to lengths, so ",[33,2588,2589],{},"translate(8cqi)"," or a keyframe declaring ",[33,2592,2593],{},"transform: translateX(60cqi)"," is valid anywhere a length is accepted, provided some ancestor has ",[33,2596,403],{}," set to ",[33,2599,118],{}," or ",[33,2602,121],{},[14,2604,2605,2608],{},[46,2606,2607],{},"Does animating with container units cost more performance than pixels?","\nNo meaningful difference at run time. The unit resolves to a pixel length during style computation, and the resulting transform still runs on the compositor. The extra work happens only when the container resizes and styles are recomputed.",[14,2610,2611,2614,2615,2617],{},[46,2612,2613],{},"Should the container decide whether motion happens at all?","\nIt can decide whether motion is appropriate, but never whether it is permitted. Container size chooses the amount and shape of movement; ",[33,2616,179],{}," holds a veto that must override any container-driven choice.",[84,2619],{},[87,2621,2623],{"id":2622},"related","Related",[56,2625,2626,2640,2646,2652,2658],{},[59,2627,2628,2632,2633,65,2635,2637,2638,132],{},[27,2629,2631],{"href":2630},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-that-scales-with-container-size\u002F","Motion That Scales with Container Size"," — ",[33,2634,64],{},[33,2636,68],{}," as travel distances, and durations derived with ",[33,2639,2276],{},[59,2641,2642,2645],{},[27,2643,2644],{"href":2135},"Container Query Hover Affordances"," — swapping hover-to-reveal for a persistent control when space is tight.",[59,2647,2648,2651],{},[27,2649,2650],{"href":365},"Suppressing Motion in Small Containers"," — removing animation below a size floor without the result feeling broken.",[59,2653,2654,2657],{},[27,2655,2656],{"href":108},"Container Query Syntax Basics"," — the cross-area foundation for every rule on this page.",[59,2659,2660,2664,2665,2668],{},[27,2661,2663],{"href":2662},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations\u002F","Container-Query-Triggered Keyframe Animations"," — switching ",[33,2666,2667],{},"animation-name"," per container size.",[2670,2671,2672],"style",{},"html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}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 .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}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}",{"title":606,"searchDepth":624,"depth":624,"links":2674},[2675,2676,2677,2678,2686,2687,2688,2689,2690,2691,2692],{"id":89,"depth":624,"text":90},{"id":192,"depth":624,"text":193},{"id":372,"depth":624,"text":373},{"id":583,"depth":624,"text":584,"children":2679},[2680,2681,2682,2683,2684,2685],{"id":588,"depth":637,"text":589},{"id":643,"depth":637,"text":644},{"id":788,"depth":637,"text":789},{"id":933,"depth":637,"text":934},{"id":1165,"depth":637,"text":1166},{"id":1256,"depth":637,"text":1257},{"id":1328,"depth":624,"text":1329},{"id":2146,"depth":624,"text":2147},{"id":2226,"depth":624,"text":2227},{"id":2305,"depth":624,"text":2306},{"id":2449,"depth":624,"text":2450},{"id":2570,"depth":624,"text":2571},{"id":2622,"depth":624,"text":2623},"Design transitions and keyframes around the space a component actually occupies, using @container and cqi units so travel distance and pacing fit the box.","md",{"pageTitle":2696,"datePublished":2697,"dateModified":2697,"faq":2698},"Container-Aware Motion with @container","2026-07-20",[2699,2701,2703,2705],{"q":2576,"a":2700},"Responsive motion changes with the viewport, so a component in a narrow sidebar on a large screen still gets desktop-sized movement. Container-aware motion measures the element's own containing box with @container and cqi units, so the same component moves less in a narrow slot and more in a wide one.",{"q":2585,"a":2702},"Yes. Container query units resolve to lengths, so translate(8cqi) or a keyframe with transform: translateX(60cqi) is valid anywhere a length is accepted, provided some ancestor has container-type set to size or inline-size.",{"q":2607,"a":2704},"No meaningful difference at run time. The unit resolves to a pixel length during style computation, and the resulting transform still runs on the compositor. The extra work happens only when the container resizes and styles are recomputed.",{"q":2613,"a":2706},"It can decide whether motion is appropriate, but never whether it is permitted. Container size chooses the amount and shape of movement; prefers-reduced-motion holds a veto that must override any container-driven choice.","\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion",{"title":5,"description":2693},"css-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Findex","IRkT1x5KvrI5dt_L6umDcTwqOitW02VuepNWePeSx5w",[2712,2715,2718,2721,2724,2727,2730,2733,2736,2737,2740,2743,2746,2749,2752,2755,2758,2761,2764,2767,2770,2773,2776,2779,2782,2785,2788,2791,2794,2797,2800,2803,2806,2809,2812,2815,2818,2821,2824,2827,2830,2833,2836,2839,2842,2845,2848,2851,2854,2857,2860,2863,2866,2869,2872,2875,2878,2881,2884,2886,2889,2892,2895,2898,2901,2904,2907,2910,2913,2916,2919,2921,2924,2927,2930,2933,2936,2939,2942,2945,2948,2951,2954,2957,2960,2963,2966,2969],{"path":2713,"title":2714},"\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":2716,"title":2717},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":2719,"title":2720},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":2722,"title":2723},"\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":2725,"title":2726},"\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":2728,"title":2729},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":2731,"title":2732},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":2734,"title":2735},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":2707,"title":5},{"path":2738,"title":2739},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-that-scales-with-container-size","Motion That Scales with Container Size: cqi, cqb, and Derived Durations",{"path":2741,"title":2742},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":2744,"title":2745},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":2747,"title":2748},"\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":2750,"title":2751},"\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":2753,"title":2754},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":2756,"title":2757},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":2759,"title":2760},"\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":2762,"title":2763},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":2765,"title":2766},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":2768,"title":2769},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":2771,"title":2772},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":2774,"title":2775},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":2777,"title":2778},"\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":2780,"title":2781},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":2783,"title":2784},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":2786,"title":2787},"\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":2789,"title":2790},"\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":2792,"title":2793},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":2795,"title":2796},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":2798,"title":2799},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":2801,"title":2802},"\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":2804,"title":2805},"\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":2807,"title":2808},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":2810,"title":2811},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":2813,"title":2814},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":2816,"title":2817},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":2819,"title":2820},"\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":2822,"title":2823},"\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":2825,"title":2826},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":2828,"title":2829},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":2831,"title":2832},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":2834,"title":2835},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":2837,"title":2838},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":2840,"title":2841},"\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":2843,"title":2844},"\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":2846,"title":2847},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":2849,"title":2850},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":2852,"title":2853},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":2855,"title":2856},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":2858,"title":2859},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":2861,"title":2862},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":2864,"title":2865},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":2867,"title":2868},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":2870,"title":2871},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":2873,"title":2874},"\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":2876,"title":2877},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":2879,"title":2880},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":2882,"title":2883},"\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":2885,"title":2656},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics",{"path":2887,"title":2888},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":2890,"title":2891},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":2893,"title":2894},"\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":2896,"title":2897},"\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":2899,"title":2900},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":2902,"title":2903},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":2905,"title":2906},"\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":2908,"title":2909},"\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":2911,"title":2912},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":2914,"title":2915},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":2917,"title":2918},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":2920,"title":40},"\u002Fmastering-container-queries-responsive-layouts",{"path":2922,"title":2923},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":2925,"title":2926},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":2928,"title":2929},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":2931,"title":2932},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":2934,"title":2935},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":2937,"title":2938},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":2940,"title":2941},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":2943,"title":2944},"\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":2946,"title":2947},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":2949,"title":2950},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":2952,"title":2953},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":2955,"title":2956},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":2958,"title":2959},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":2961,"title":2962},"\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":2964,"title":2965},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":2967,"title":2968},"\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":2970,"title":2971},"\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",1784566156666]