[{"data":1,"prerenderedAt":1908},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers\u002F":3,"content-all-pages":1646},{"id":4,"title":5,"body":6,"description":1628,"extension":1629,"meta":1630,"navigation":382,"path":1642,"seo":1643,"stem":1644,"__hash__":1645},"content\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers\u002Findex.md","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"type":7,"value":8,"toc":1618},"minimark",[9,13,28,31,36,49,52,55,58,60,64,71,172,176,351,1043,1053,1056,1058,1062,1077,1091,1105,1179,1181,1185,1196,1484,1492,1494,1498,1514,1516,1520,1537,1539,1543,1550,1556,1562,1571,1573,1577,1614],[10,11,5],"h1",{"id":12},"suppressing-motion-in-small-containers-deliberately-animating-nothing",[14,15,16,17,22,23,27],"p",{},"Most container-aware technique is about making motion fit. This page is about the other conclusion — that below a certain size the honest design decision is no motion at all, and that shipping a still component in a tight slot is a feature rather than a shortcut. A carousel drift, a parallax offset, or a slide-in that was tuned in a 700px hero does not become a gentler version of itself at 260px; it becomes a few pixels of twitch, which readers experience as a rendering fault. This page is part of the ",[18,19,21],"a",{"href":20},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002F","container-aware motion"," section and picks up exactly where the proportional approach in ",[18,24,26],{"href":25},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-that-scales-with-container-size\u002F","motion that scales with container size"," runs out of road.",[29,30],"hr",{},[32,33,35],"h2",{"id":34},"the-case-for-a-motion-floor","The case for a motion floor",[14,37,38,39,43,44,48],{},"Perceived movement has a lower bound. Below roughly six to eight pixels of travel, over a duration in the 200-400ms band typical of interface transitions, the eye stops resolving a direction and starts registering only that something changed — the same signal it gets from a repaint artefact, a subpixel reflow, or a flickering GPU layer. Proportional travel walks straight into that band: a distance written as ",[40,41,42],"code",{},"8cqi"," is a comfortable 56px at 700px and an unusable 21px at 260px, and clamping it to a floor of 8px does not save the effect, because the problem is not that 8px is too small to see. It is that 8px of travel inside a 260px component is too small to read ",[45,46,47],"em",{},"as travel",".",[14,50,51],{},"Small containers make it worse in three specific ways. Travel that is a large fraction of the container reads as the whole component moving rather than an element moving within it. Ambient loops — drifting badges, sweeping shimmer, a slow parallax — sit permanently in peripheral vision in a dense sidebar, where a dozen instances of them compete for attention that none of them deserve. And small containers are typically found in dense contexts, list rails and filter panels and compact dashboards, where the same component is repeated many times and any per-instance ambient motion multiplies into visual noise.",[14,53,54],{},"The alternative approaches are worse. Slowing the animation down does not help, because a slower tiny movement is a longer-lived artefact rather than a clearer gesture. Detecting the size in JavaScript and stripping a class works but pays a script and a measurement for a decision CSS can make in the cascade. A blanket removal of the effect everywhere throws away motion that is genuinely useful at the sizes where the component has room. A container floor is the smallest correct intervention: keep the effect where it works, remove it where it does not, express both in one stylesheet.",[14,56,57],{},"The tradeoff to be honest about is threshold churn. A hard-coded floor is a magic number that needs revisiting when the component's typography or padding changes, and a container that resizes across the boundary during a sidebar animation will flip motion on and off mid-drag. Both are manageable — put the floor in a custom property, and avoid animating the container's own width — but neither disappears.",[29,59],{},[32,61,63],{"id":62},"complete-working-implementation","Complete working implementation",[14,65,66,67,70],{},"The tile below grants motion rather than removing it. Nothing animates in the base rules; a single ",[40,68,69],{},"@container"," block above the floor switches the badge drift and the progress sweep on. Drag the frame under 360px and the component goes completely still while keeping its layout, its colour, and its content exactly as they were.",[72,73,79,80,79,84,79,88,79,95,79,105,79,110,79,120,79,125,79,131,79,136,79,140,79,142,79,146,79,149,79,157,79,162,79,167],"svg",{"viewBox":74,"role":75,"ariaLabel":76,"xmlns":77,"style":78},"0 0 720 340","img","A container width floor dividing a suppressed zone from an animated zone, with the reduced-motion preference overriding both","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[81,82,83],"title",{},"A motion floor with a user-preference override",[85,86,87],"desc",{},"Container widths below the floor resolve to no animation; widths above it enable animation. A band underneath shows the reduced motion preference overriding both zones.",[89,90,94],"text",{"x":91,"y":92,"style":93},"360","28","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","A floor for motion, a veto above it",[96,97],"line",{"x1":91,"y1":98,"x2":91,"y2":99,"stroke":100,"strokeWidth":101,"strokeDashArray":102},"76","200","#7aa2ff","2",[103,104],"6","5",[89,106,109],{"x":91,"y":107,"style":108},"66","text-anchor:middle;fill:#7aa2ff;font:12px ui-monospace,monospace","floor: 360px",[111,112],"rect",{"x":113,"y":114,"width":115,"height":116,"rx":117,"fill":118,"opacity":119},"40","90","300","100","12","currentColor","0.08",[111,121],{"x":113,"y":114,"width":115,"height":116,"rx":117,"fill":122,"stroke":118,"strokeWidth":123,"opacity":124},"none","1.5","0.5",[89,126,130],{"x":127,"y":128,"style":129},"190","126","text-anchor:middle;fill:currentColor;font:600 14px sans-serif","below the floor",[89,132,135],{"x":127,"y":133,"style":134},"158","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace;opacity:0.8","no animation declared",[111,137],{"x":138,"y":114,"width":115,"height":116,"rx":117,"fill":100,"opacity":139},"380","0.16",[111,141],{"x":138,"y":114,"width":115,"height":116,"rx":117,"fill":122,"stroke":100,"strokeWidth":123},[89,143,145],{"x":144,"y":128,"style":129},"530","above the floor",[89,147,148],{"x":144,"y":133,"style":134},"animation granted",[111,150],{"x":113,"y":151,"width":152,"height":153,"rx":154,"fill":122,"stroke":100,"strokeWidth":123,"strokeDashArray":155},"228","640","52","10",[156,156],"4",[89,158,161],{"x":91,"y":159,"style":160},"252","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","prefers-reduced-motion: reduce",[89,163,166],{"x":91,"y":164,"style":165},"271","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.75","removes motion in both zones",[89,168,171],{"x":91,"y":169,"style":170},"316","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.6","size is an opinion; the preference is a rule",[173,174],"live-demo",{"name":175},"cmotion-motion-floor",[177,178,183],"pre",{"className":179,"code":180,"language":181,"meta":182,"style":182},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cdiv class=\"tile-wrap\">\n  \u003Carticle class=\"tile\">\n    \u003Cspan class=\"tile__badge\">Live\u003C\u002Fspan>\n    \u003Ch3 class=\"tile__head\">Deploy queue\u003C\u002Fh3>\n    \u003Cdiv class=\"tile__bar\">\u003Cspan class=\"tile__fill\">\u003C\u002Fspan>\u003C\u002Fdiv>\n    \u003Cp class=\"tile__note\">Motion only above the width floor.\u003C\u002Fp>\n  \u003C\u002Farticle>\n\u003C\u002Fdiv>\n","html","",[40,184,185,211,229,251,273,310,331,341],{"__ignoreMap":182},[186,187,189,193,197,201,204,208],"span",{"class":96,"line":188},1,[186,190,192],{"class":191},"suds8","\u003C",[186,194,196],{"class":195},"sne4z","div",[186,198,200],{"class":199},"s-5SL"," class",[186,202,203],{"class":191},"=",[186,205,207],{"class":206},"sT6z2","\"tile-wrap\"",[186,209,210],{"class":191},">\n",[186,212,214,217,220,222,224,227],{"class":96,"line":213},2,[186,215,216],{"class":191},"  \u003C",[186,218,219],{"class":195},"article",[186,221,200],{"class":199},[186,223,203],{"class":191},[186,225,226],{"class":206},"\"tile\"",[186,228,210],{"class":191},[186,230,232,235,237,239,241,244,247,249],{"class":96,"line":231},3,[186,233,234],{"class":191},"    \u003C",[186,236,186],{"class":195},[186,238,200],{"class":199},[186,240,203],{"class":191},[186,242,243],{"class":206},"\"tile__badge\"",[186,245,246],{"class":191},">Live\u003C\u002F",[186,248,186],{"class":195},[186,250,210],{"class":191},[186,252,254,256,259,261,263,266,269,271],{"class":96,"line":253},4,[186,255,234],{"class":191},[186,257,258],{"class":195},"h3",[186,260,200],{"class":199},[186,262,203],{"class":191},[186,264,265],{"class":206},"\"tile__head\"",[186,267,268],{"class":191},">Deploy queue\u003C\u002F",[186,270,258],{"class":195},[186,272,210],{"class":191},[186,274,276,278,280,282,284,287,290,292,294,296,299,302,304,306,308],{"class":96,"line":275},5,[186,277,234],{"class":191},[186,279,196],{"class":195},[186,281,200],{"class":199},[186,283,203],{"class":191},[186,285,286],{"class":206},"\"tile__bar\"",[186,288,289],{"class":191},">\u003C",[186,291,186],{"class":195},[186,293,200],{"class":199},[186,295,203],{"class":191},[186,297,298],{"class":206},"\"tile__fill\"",[186,300,301],{"class":191},">\u003C\u002F",[186,303,186],{"class":195},[186,305,301],{"class":191},[186,307,196],{"class":195},[186,309,210],{"class":191},[186,311,313,315,317,319,321,324,327,329],{"class":96,"line":312},6,[186,314,234],{"class":191},[186,316,14],{"class":195},[186,318,200],{"class":199},[186,320,203],{"class":191},[186,322,323],{"class":206},"\"tile__note\"",[186,325,326],{"class":191},">Motion only above the width floor.\u003C\u002F",[186,328,14],{"class":195},[186,330,210],{"class":191},[186,332,334,337,339],{"class":96,"line":333},7,[186,335,336],{"class":191},"  \u003C\u002F",[186,338,219],{"class":195},[186,340,210],{"class":191},[186,342,344,347,349],{"class":96,"line":343},8,[186,345,346],{"class":191},"\u003C\u002F",[186,348,196],{"class":195},[186,350,210],{"class":191},[177,352,356],{"className":353,"code":354,"language":355,"meta":182,"style":182},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast",".tile-wrap { container-type: inline-size; container-name: tile; }\n\n.tile {\n  padding: 1rem;\n  border: 1px solid var(--demo-border);\n  border-radius: 12px;\n  background: var(--demo-surface);\n}\n.tile__head { margin: .5rem 0 .7rem; font-size: 1rem; color: var(--demo-fg); }\n.tile__note { margin: .7rem 0 0; color: var(--demo-muted); font-size: .82rem; }\n\n.tile__badge {\n  display: inline-block;\n  padding: .2rem .55rem;\n  border-radius: 999px;\n  background: var(--demo-accent);\n  color: var(--demo-bg);\n  font-size: .72rem;\n}\n\n.tile__bar {\n  height: 8px;\n  border-radius: 4px;\n  background: var(--demo-border);\n  overflow: hidden;\n}\n.tile__fill {\n  display: block;\n  height: 100%;\n  width: 40%;\n  border-radius: 4px;\n  background: var(--demo-accent);\n}\n\n\u002F* Motion is opt-IN, granted only once the container is wide enough\n   for the travel to read as movement rather than vibration. *\u002F\n@container tile (min-width: 360px) {\n  .tile__badge { animation: drift 2.6s ease-in-out infinite alternate; }\n  .tile__fill  { animation: sweep 2.6s ease-in-out infinite alternate; }\n}\n\n@keyframes drift { to { transform: translateX(4cqi); } }\n@keyframes sweep { to { width: 85%; } }\n\n\u002F* The user preference outranks the container every time. *\u002F\n@media (prefers-reduced-motion: reduce) {\n  .tile__badge, .tile__fill { animation: none; }\n}\n","css",[40,357,358,378,384,392,410,438,451,468,473,528,577,582,590,603,622,636,652,669,684,689,694,702,717,730,745,758,763,771,783,797,811,824,839,844,849,856,862,870,901,927,932,937,971,998,1003,1009,1018,1038],{"__ignoreMap":182},[186,359,360,363,366,369,372,375],{"class":96,"line":188},[186,361,362],{"class":199},".tile-wrap",[186,364,365],{"class":191}," { ",[186,367,368],{"class":199},"container-type",[186,370,371],{"class":191},": inline-size; ",[186,373,374],{"class":199},"container-name",[186,376,377],{"class":191},": tile; }\n",[186,379,380],{"class":96,"line":213},[186,381,383],{"emptyLinePlaceholder":382},true,"\n",[186,385,386,389],{"class":96,"line":231},[186,387,388],{"class":199},".tile",[186,390,391],{"class":191}," {\n",[186,393,394,397,400,403,407],{"class":96,"line":253},[186,395,396],{"class":199},"  padding",[186,398,399],{"class":191},": ",[186,401,402],{"class":199},"1",[186,404,406],{"class":405},"sHUrx","rem",[186,408,409],{"class":191},";\n",[186,411,412,415,417,419,422,425,428,431,435],{"class":96,"line":275},[186,413,414],{"class":199},"  border",[186,416,399],{"class":191},[186,418,402],{"class":199},[186,420,421],{"class":405},"px",[186,423,424],{"class":199}," solid",[186,426,427],{"class":199}," var",[186,429,430],{"class":191},"(",[186,432,434],{"class":433},"soyes","--demo-border",[186,436,437],{"class":191},");\n",[186,439,440,443,445,447,449],{"class":96,"line":312},[186,441,442],{"class":199},"  border-radius",[186,444,399],{"class":191},[186,446,117],{"class":199},[186,448,421],{"class":405},[186,450,409],{"class":191},[186,452,453,456,458,461,463,466],{"class":96,"line":333},[186,454,455],{"class":199},"  background",[186,457,399],{"class":191},[186,459,460],{"class":199},"var",[186,462,430],{"class":191},[186,464,465],{"class":433},"--demo-surface",[186,467,437],{"class":191},[186,469,470],{"class":96,"line":343},[186,471,472],{"class":191},"}\n",[186,474,476,479,481,484,486,489,491,494,497,499,502,505,507,509,511,513,516,518,520,522,525],{"class":96,"line":475},9,[186,477,478],{"class":199},".tile__head",[186,480,365],{"class":191},[186,482,483],{"class":199},"margin",[186,485,399],{"class":191},[186,487,488],{"class":199},".5",[186,490,406],{"class":405},[186,492,493],{"class":199}," 0",[186,495,496],{"class":199}," .7",[186,498,406],{"class":405},[186,500,501],{"class":191},"; ",[186,503,504],{"class":199},"font-size",[186,506,399],{"class":191},[186,508,402],{"class":199},[186,510,406],{"class":405},[186,512,501],{"class":191},[186,514,515],{"class":199},"color",[186,517,399],{"class":191},[186,519,460],{"class":199},[186,521,430],{"class":191},[186,523,524],{"class":433},"--demo-fg",[186,526,527],{"class":191},"); }\n",[186,529,531,534,536,538,540,543,545,547,549,551,553,555,557,559,562,565,567,569,572,574],{"class":96,"line":530},10,[186,532,533],{"class":199},".tile__note",[186,535,365],{"class":191},[186,537,483],{"class":199},[186,539,399],{"class":191},[186,541,542],{"class":199},".7",[186,544,406],{"class":405},[186,546,493],{"class":199},[186,548,493],{"class":199},[186,550,501],{"class":191},[186,552,515],{"class":199},[186,554,399],{"class":191},[186,556,460],{"class":199},[186,558,430],{"class":191},[186,560,561],{"class":433},"--demo-muted",[186,563,564],{"class":191},"); ",[186,566,504],{"class":199},[186,568,399],{"class":191},[186,570,571],{"class":199},".82",[186,573,406],{"class":405},[186,575,576],{"class":191},"; }\n",[186,578,580],{"class":96,"line":579},11,[186,581,383],{"emptyLinePlaceholder":382},[186,583,585,588],{"class":96,"line":584},12,[186,586,587],{"class":199},".tile__badge",[186,589,391],{"class":191},[186,591,593,596,598,601],{"class":96,"line":592},13,[186,594,595],{"class":199},"  display",[186,597,399],{"class":191},[186,599,600],{"class":199},"inline-block",[186,602,409],{"class":191},[186,604,606,608,610,613,615,618,620],{"class":96,"line":605},14,[186,607,396],{"class":199},[186,609,399],{"class":191},[186,611,612],{"class":199},".2",[186,614,406],{"class":405},[186,616,617],{"class":199}," .55",[186,619,406],{"class":405},[186,621,409],{"class":191},[186,623,625,627,629,632,634],{"class":96,"line":624},15,[186,626,442],{"class":199},[186,628,399],{"class":191},[186,630,631],{"class":199},"999",[186,633,421],{"class":405},[186,635,409],{"class":191},[186,637,639,641,643,645,647,650],{"class":96,"line":638},16,[186,640,455],{"class":199},[186,642,399],{"class":191},[186,644,460],{"class":199},[186,646,430],{"class":191},[186,648,649],{"class":433},"--demo-accent",[186,651,437],{"class":191},[186,653,655,658,660,662,664,667],{"class":96,"line":654},17,[186,656,657],{"class":199},"  color",[186,659,399],{"class":191},[186,661,460],{"class":199},[186,663,430],{"class":191},[186,665,666],{"class":433},"--demo-bg",[186,668,437],{"class":191},[186,670,672,675,677,680,682],{"class":96,"line":671},18,[186,673,674],{"class":199},"  font-size",[186,676,399],{"class":191},[186,678,679],{"class":199},".72",[186,681,406],{"class":405},[186,683,409],{"class":191},[186,685,687],{"class":96,"line":686},19,[186,688,472],{"class":191},[186,690,692],{"class":96,"line":691},20,[186,693,383],{"emptyLinePlaceholder":382},[186,695,697,700],{"class":96,"line":696},21,[186,698,699],{"class":199},".tile__bar",[186,701,391],{"class":191},[186,703,705,708,710,713,715],{"class":96,"line":704},22,[186,706,707],{"class":199},"  height",[186,709,399],{"class":191},[186,711,712],{"class":199},"8",[186,714,421],{"class":405},[186,716,409],{"class":191},[186,718,720,722,724,726,728],{"class":96,"line":719},23,[186,721,442],{"class":199},[186,723,399],{"class":191},[186,725,156],{"class":199},[186,727,421],{"class":405},[186,729,409],{"class":191},[186,731,733,735,737,739,741,743],{"class":96,"line":732},24,[186,734,455],{"class":199},[186,736,399],{"class":191},[186,738,460],{"class":199},[186,740,430],{"class":191},[186,742,434],{"class":433},[186,744,437],{"class":191},[186,746,748,751,753,756],{"class":96,"line":747},25,[186,749,750],{"class":199},"  overflow",[186,752,399],{"class":191},[186,754,755],{"class":199},"hidden",[186,757,409],{"class":191},[186,759,761],{"class":96,"line":760},26,[186,762,472],{"class":191},[186,764,766,769],{"class":96,"line":765},27,[186,767,768],{"class":199},".tile__fill",[186,770,391],{"class":191},[186,772,774,776,778,781],{"class":96,"line":773},28,[186,775,595],{"class":199},[186,777,399],{"class":191},[186,779,780],{"class":199},"block",[186,782,409],{"class":191},[186,784,786,788,790,792,795],{"class":96,"line":785},29,[186,787,707],{"class":199},[186,789,399],{"class":191},[186,791,116],{"class":199},[186,793,794],{"class":405},"%",[186,796,409],{"class":191},[186,798,800,803,805,807,809],{"class":96,"line":799},30,[186,801,802],{"class":199},"  width",[186,804,399],{"class":191},[186,806,113],{"class":199},[186,808,794],{"class":405},[186,810,409],{"class":191},[186,812,814,816,818,820,822],{"class":96,"line":813},31,[186,815,442],{"class":199},[186,817,399],{"class":191},[186,819,156],{"class":199},[186,821,421],{"class":405},[186,823,409],{"class":191},[186,825,827,829,831,833,835,837],{"class":96,"line":826},32,[186,828,455],{"class":199},[186,830,399],{"class":191},[186,832,460],{"class":199},[186,834,430],{"class":191},[186,836,649],{"class":433},[186,838,437],{"class":191},[186,840,842],{"class":96,"line":841},33,[186,843,472],{"class":191},[186,845,847],{"class":96,"line":846},34,[186,848,383],{"emptyLinePlaceholder":382},[186,850,852],{"class":96,"line":851},35,[186,853,855],{"class":854},"sLBg1","\u002F* Motion is opt-IN, granted only once the container is wide enough\n",[186,857,859],{"class":96,"line":858},36,[186,860,861],{"class":854},"   for the travel to read as movement rather than vibration. *\u002F\n",[186,863,865,867],{"class":96,"line":864},37,[186,866,69],{"class":405},[186,868,869],{"class":191}," tile (min-width: 360px) {\n",[186,871,873,876,878,881,884,887,890,893,896,899],{"class":96,"line":872},38,[186,874,875],{"class":199},"  .tile__badge",[186,877,365],{"class":191},[186,879,880],{"class":199},"animation",[186,882,883],{"class":191},": drift ",[186,885,886],{"class":199},"2.6",[186,888,889],{"class":405},"s",[186,891,892],{"class":199}," ease-in-out",[186,894,895],{"class":199}," infinite",[186,897,898],{"class":199}," alternate",[186,900,576],{"class":191},[186,902,904,907,910,912,915,917,919,921,923,925],{"class":96,"line":903},39,[186,905,906],{"class":199},"  .tile__fill",[186,908,909],{"class":191},"  { ",[186,911,880],{"class":199},[186,913,914],{"class":191},": sweep ",[186,916,886],{"class":199},[186,918,889],{"class":405},[186,920,892],{"class":199},[186,922,895],{"class":199},[186,924,898],{"class":199},[186,926,576],{"class":191},[186,928,930],{"class":96,"line":929},40,[186,931,472],{"class":191},[186,933,935],{"class":96,"line":934},41,[186,936,383],{"emptyLinePlaceholder":382},[186,938,940,943,946,948,951,953,956,958,961,963,965,968],{"class":96,"line":939},42,[186,941,942],{"class":405},"@keyframes",[186,944,945],{"class":433}," drift",[186,947,365],{"class":191},[186,949,950],{"class":199},"to",[186,952,365],{"class":191},[186,954,955],{"class":199},"transform",[186,957,399],{"class":191},[186,959,960],{"class":199},"translateX",[186,962,430],{"class":191},[186,964,156],{"class":199},[186,966,967],{"class":405},"cqi",[186,969,970],{"class":191},"); } }\n",[186,972,974,976,979,981,983,985,988,990,993,995],{"class":96,"line":973},43,[186,975,942],{"class":405},[186,977,978],{"class":433}," sweep",[186,980,365],{"class":191},[186,982,950],{"class":199},[186,984,365],{"class":191},[186,986,987],{"class":199},"width",[186,989,399],{"class":191},[186,991,992],{"class":199},"85",[186,994,794],{"class":405},[186,996,997],{"class":191},"; } }\n",[186,999,1001],{"class":96,"line":1000},44,[186,1002,383],{"emptyLinePlaceholder":382},[186,1004,1006],{"class":96,"line":1005},45,[186,1007,1008],{"class":854},"\u002F* The user preference outranks the container every time. *\u002F\n",[186,1010,1012,1015],{"class":96,"line":1011},46,[186,1013,1014],{"class":405},"@media",[186,1016,1017],{"class":191}," (prefers-reduced-motion: reduce) {\n",[186,1019,1021,1023,1026,1028,1030,1032,1034,1036],{"class":96,"line":1020},47,[186,1022,875],{"class":199},[186,1024,1025],{"class":191},", ",[186,1027,768],{"class":199},[186,1029,365],{"class":191},[186,1031,880],{"class":199},[186,1033,399],{"class":191},[186,1035,122],{"class":199},[186,1037,576],{"class":191},[186,1039,1041],{"class":96,"line":1040},48,[186,1042,472],{"class":191},[1044,1045,1046],"blockquote",{},[14,1047,1048,1049,1052],{},"The ",[40,1050,1051],{},"--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,1054,1055],{},"The suppressed rendering is not a degraded one. The badge still sits where it sits, the bar still shows 40%, the colours and spacing are untouched — the only thing missing is the drift, which was ambient decoration. Nothing that carried information was in the motion, and that is the test a suppressible effect has to pass before you make it suppressible.",[29,1057],{},[32,1059,1061],{"id":1060},"the-key-technique-grant-motion-do-not-revoke-it","The key technique: grant motion, do not revoke it",[14,1063,1064,1065,1068,1069,1072,1073,1076],{},"The structural choice that makes this maintainable is writing the animation ",[45,1066,1067],{},"inside"," the ",[40,1070,1071],{},"min-width"," query rather than writing it at the top level and cancelling it inside a ",[40,1074,1075],{},"max-width"," query. The two look equivalent and are not.",[14,1078,1079,1080,1082,1083,1086,1087,1090],{},"Granting means the still state is the cascade's base. Every failure — an engine without container query support, a mistyped container name, a wrapper that lost its ",[40,1081,368],{}," in a refactor — resolves to ",[45,1084,1085],{},"no animation",", which is safe, quiet, and indistinguishable from a deliberate choice. Revoking means the animated state is the base and the cancellation is conditional, so every one of those same failures resolves to ",[45,1088,1089],{},"animation everywhere",", including the 240px slots where it was specifically judged unacceptable.",[14,1092,1093,1094,1097,1098,1100,1101,1104],{},"Granting also avoids a subtle cancellation bug. ",[40,1095,1096],{},"animation: none"," inside a ",[40,1099,1075],{}," block removes the animation, but it does not undo any base styles that the animation was compensating for. If the base rule set ",[40,1102,1103],{},"opacity: 0"," expecting an entrance keyframe to bring it to 1, cancelling the animation leaves the element permanently invisible. Under the grant model that cannot happen, because the base rules never contain an entrance start state at all — they describe the finished, resting element, and the keyframes are the only thing that ever moves it away from that. When you do have to revoke, reset every property the keyframes touched in the same block:",[177,1106,1108],{"className":353,"code":1107,"language":355,"meta":182,"style":182},"\u002F* If you must revoke rather than grant, restore the resting state too. *\u002F\n@container tile (max-width: 359px) {\n  .panel {\n    animation: none;\n    opacity: 1;        \u002F* undo the entrance start state *\u002F\n    transform: none;   \u002F* undo any offset the keyframes assumed *\u002F\n  }\n}\n",[40,1109,1110,1115,1122,1129,1140,1155,1170,1175],{"__ignoreMap":182},[186,1111,1112],{"class":96,"line":188},[186,1113,1114],{"class":854},"\u002F* If you must revoke rather than grant, restore the resting state too. *\u002F\n",[186,1116,1117,1119],{"class":96,"line":213},[186,1118,69],{"class":405},[186,1120,1121],{"class":191}," tile (max-width: 359px) {\n",[186,1123,1124,1127],{"class":96,"line":231},[186,1125,1126],{"class":199},"  .panel",[186,1128,391],{"class":191},[186,1130,1131,1134,1136,1138],{"class":96,"line":253},[186,1132,1133],{"class":199},"    animation",[186,1135,399],{"class":191},[186,1137,122],{"class":199},[186,1139,409],{"class":191},[186,1141,1142,1145,1147,1149,1152],{"class":96,"line":275},[186,1143,1144],{"class":199},"    opacity",[186,1146,399],{"class":191},[186,1148,402],{"class":199},[186,1150,1151],{"class":191},";        ",[186,1153,1154],{"class":854},"\u002F* undo the entrance start state *\u002F\n",[186,1156,1157,1160,1162,1164,1167],{"class":96,"line":312},[186,1158,1159],{"class":199},"    transform",[186,1161,399],{"class":191},[186,1163,122],{"class":199},[186,1165,1166],{"class":191},";   ",[186,1168,1169],{"class":854},"\u002F* undo any offset the keyframes assumed *\u002F\n",[186,1171,1172],{"class":96,"line":333},[186,1173,1174],{"class":191},"  }\n",[186,1176,1177],{"class":96,"line":343},[186,1178,472],{"class":191},[29,1180],{},[32,1182,1184],{"id":1183},"variation-keeping-the-still-version-alive-with-an-instant-state-change","Variation: keeping the still version alive with an instant state change",[14,1186,1187,1188,1191,1192,1195],{},"The failure mode of suppression is a component that stops responding. If hover feedback consisted entirely of a lift, removing the lift removes the feedback, and the narrow variant feels dead rather than calm. The fix is to separate ",[45,1189,1190],{},"acknowledgement"," from ",[45,1193,1194],{},"movement",": below the floor, keep a state change that is instantaneous rather than animated.",[177,1197,1199],{"className":353,"code":1198,"language":355,"meta":182,"style":182},"\u002F* Base: acknowledgement with no travel — instant, works at any size. *\u002F\n.row {\n  border-inline-start: 3px solid transparent;\n  background: transparent;\n}\n.row:hover,\n.row:focus-within {\n  border-inline-start-color: currentColor;\n  background: color-mix(in srgb, currentColor 6%, transparent);\n}\n\n\u002F* Above the floor, add the movement on top of the same acknowledgement. *\u002F\n@container tile (min-width: 360px) {\n  .row {\n    transition: transform 200ms cubic-bezier(.2, .8, .2, 1),\n                background 200ms ease;\n  }\n  .row:hover,\n  .row:focus-within { transform: translateX(clamp(4px, 1.5cqi, 12px)); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .row { transition: none; }\n  .row:hover, .row:focus-within { transform: none; }\n}\n",[40,1200,1201,1206,1213,1232,1243,1247,1255,1262,1273,1305,1309,1313,1318,1324,1331,1367,1383,1387,1394,1433,1437,1441,1447,1462,1480],{"__ignoreMap":182},[186,1202,1203],{"class":96,"line":188},[186,1204,1205],{"class":854},"\u002F* Base: acknowledgement with no travel — instant, works at any size. *\u002F\n",[186,1207,1208,1211],{"class":96,"line":213},[186,1209,1210],{"class":199},".row",[186,1212,391],{"class":191},[186,1214,1215,1218,1220,1223,1225,1227,1230],{"class":96,"line":231},[186,1216,1217],{"class":199},"  border-inline-start",[186,1219,399],{"class":191},[186,1221,1222],{"class":199},"3",[186,1224,421],{"class":405},[186,1226,424],{"class":199},[186,1228,1229],{"class":199}," transparent",[186,1231,409],{"class":191},[186,1233,1234,1236,1238,1241],{"class":96,"line":253},[186,1235,455],{"class":199},[186,1237,399],{"class":191},[186,1239,1240],{"class":199},"transparent",[186,1242,409],{"class":191},[186,1244,1245],{"class":96,"line":275},[186,1246,472],{"class":191},[186,1248,1249,1252],{"class":96,"line":312},[186,1250,1251],{"class":199},".row:hover",[186,1253,1254],{"class":191},",\n",[186,1256,1257,1260],{"class":96,"line":333},[186,1258,1259],{"class":199},".row:focus-within",[186,1261,391],{"class":191},[186,1263,1264,1267,1269,1271],{"class":96,"line":343},[186,1265,1266],{"class":199},"  border-inline-start-color",[186,1268,399],{"class":191},[186,1270,118],{"class":199},[186,1272,409],{"class":191},[186,1274,1275,1277,1279,1282,1284,1287,1290,1292,1294,1297,1299,1301,1303],{"class":96,"line":475},[186,1276,455],{"class":199},[186,1278,399],{"class":191},[186,1280,1281],{"class":199},"color-mix",[186,1283,430],{"class":191},[186,1285,1286],{"class":433},"in",[186,1288,1289],{"class":199}," srgb",[186,1291,1025],{"class":191},[186,1293,118],{"class":199},[186,1295,1296],{"class":199}," 6",[186,1298,794],{"class":405},[186,1300,1025],{"class":191},[186,1302,1240],{"class":199},[186,1304,437],{"class":191},[186,1306,1307],{"class":96,"line":530},[186,1308,472],{"class":191},[186,1310,1311],{"class":96,"line":579},[186,1312,383],{"emptyLinePlaceholder":382},[186,1314,1315],{"class":96,"line":584},[186,1316,1317],{"class":854},"\u002F* Above the floor, add the movement on top of the same acknowledgement. *\u002F\n",[186,1319,1320,1322],{"class":96,"line":592},[186,1321,69],{"class":405},[186,1323,869],{"class":191},[186,1325,1326,1329],{"class":96,"line":605},[186,1327,1328],{"class":199},"  .row",[186,1330,391],{"class":191},[186,1332,1333,1336,1339,1341,1344,1347,1349,1351,1353,1356,1358,1360,1362,1364],{"class":96,"line":624},[186,1334,1335],{"class":199},"    transition",[186,1337,1338],{"class":191},": transform ",[186,1340,99],{"class":199},[186,1342,1343],{"class":405},"ms",[186,1345,1346],{"class":199}," cubic-bezier",[186,1348,430],{"class":191},[186,1350,612],{"class":199},[186,1352,1025],{"class":191},[186,1354,1355],{"class":199},".8",[186,1357,1025],{"class":191},[186,1359,612],{"class":199},[186,1361,1025],{"class":191},[186,1363,402],{"class":199},[186,1365,1366],{"class":191},"),\n",[186,1368,1369,1373,1376,1378,1381],{"class":96,"line":638},[186,1370,1372],{"class":1371},"sh5d0","                background",[186,1374,1375],{"class":199}," 200",[186,1377,1343],{"class":405},[186,1379,1380],{"class":199}," ease",[186,1382,409],{"class":191},[186,1384,1385],{"class":96,"line":654},[186,1386,1174],{"class":191},[186,1388,1389,1392],{"class":96,"line":671},[186,1390,1391],{"class":199},"  .row:hover",[186,1393,1254],{"class":191},[186,1395,1396,1399,1401,1403,1405,1407,1409,1412,1414,1416,1418,1420,1422,1424,1426,1428,1430],{"class":96,"line":686},[186,1397,1398],{"class":199},"  .row:focus-within",[186,1400,365],{"class":191},[186,1402,955],{"class":199},[186,1404,399],{"class":191},[186,1406,960],{"class":199},[186,1408,430],{"class":191},[186,1410,1411],{"class":199},"clamp",[186,1413,430],{"class":191},[186,1415,156],{"class":199},[186,1417,421],{"class":405},[186,1419,1025],{"class":191},[186,1421,123],{"class":199},[186,1423,967],{"class":405},[186,1425,1025],{"class":191},[186,1427,117],{"class":199},[186,1429,421],{"class":405},[186,1431,1432],{"class":191},")); }\n",[186,1434,1435],{"class":96,"line":691},[186,1436,472],{"class":191},[186,1438,1439],{"class":96,"line":696},[186,1440,383],{"emptyLinePlaceholder":382},[186,1442,1443,1445],{"class":96,"line":704},[186,1444,1014],{"class":405},[186,1446,1017],{"class":191},[186,1448,1449,1451,1453,1456,1458,1460],{"class":96,"line":719},[186,1450,1328],{"class":199},[186,1452,365],{"class":191},[186,1454,1455],{"class":199},"transition",[186,1457,399],{"class":191},[186,1459,122],{"class":199},[186,1461,576],{"class":191},[186,1463,1464,1466,1468,1470,1472,1474,1476,1478],{"class":96,"line":732},[186,1465,1391],{"class":199},[186,1467,1025],{"class":191},[186,1469,1259],{"class":199},[186,1471,365],{"class":191},[186,1473,955],{"class":199},[186,1475,399],{"class":191},[186,1477,122],{"class":199},[186,1479,576],{"class":191},[186,1481,1482],{"class":96,"line":747},[186,1483,472],{"class":191},[14,1485,1486,1487,1491],{},"The border and background change carry the entire semantic load; the translate is an embellishment layered over it. That ordering also means the reduced-motion block only has to remove the embellishment, never the feedback — which is precisely the structure recommended in ",[18,1488,1490],{"href":1489},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes\u002F","prefers-reduced-motion recipes"," and the reason a well-built reduced variant never needs a separate \"accessible\" design.",[29,1493],{},[32,1495,1497],{"id":1496},"accessibility-framing","Accessibility framing",[14,1499,1500,1501,1504,1505,1509,1510,48],{},"Suppressing motion by size is an editorial judgement; suppressing it by preference is an obligation, and the two must not be allowed to substitute for each other. A component whose container happens to be wide has no special licence to ignore ",[40,1502,1503],{},"prefers-reduced-motion",", and a component that is narrow is not thereby compliant. Keep the preference query outside and after every container block so it wins on cascade order regardless of specificity, and remember that WCAG 2.2 success criterion 2.3.3 concerns motion triggered by interaction — the details of what the criteria do and do not require are in ",[18,1506,1508],{"href":1507},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria\u002F","WCAG motion success criteria",". Looping ambient motion of the kind suppressed here also raises the five-second auto-playing rule from 2.2.2 if it runs indefinitely alongside content; the vestibular considerations behind large-amplitude effects are covered in ",[18,1511,1513],{"href":1512},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns\u002F","vestibular-safe animation patterns",[29,1515],{},[32,1517,1519],{"id":1518},"browser-support","Browser support",[14,1521,1522,1523,1525,1526,1528,1529,1532,1533,1536],{},"The pattern needs only size container queries and the reduced-motion media feature. Container queries are available in Chrome and Edge 105+, Safari 16+, and Firefox 110+; ",[40,1524,1503],{}," in Chrome 74+, Safari 10.1+, and Firefox 63+. Because motion is granted inside the query rather than revoked, an engine that does not understand ",[40,1527,69],{}," skips the block entirely and renders the still variant everywhere — a correct, conservative result that needs no ",[40,1530,1531],{},"@supports"," gate. If you want the older engine to keep some motion at large viewports, wrap a viewport breakpoint in ",[40,1534,1535],{},"@supports not (container-type: inline-size)"," and grant the animation there instead.",[29,1538],{},[32,1540,1542],{"id":1541},"faq","FAQ",[14,1544,1545,1549],{},[1546,1547,1548],"strong",{},"Why does a slide or parallax effect look like jitter in a small container?","\nThe travel distance shrinks with the box until it is only a few pixels, and a few pixels of movement over a few hundred milliseconds is below the threshold at which the eye reads direction. Without a perceived direction the movement registers as instability or a rendering fault rather than a transition.",[14,1551,1552,1555],{},[1546,1553,1554],{},"Should the container query or prefers-reduced-motion win?","\nThe user preference always wins. Treat the container floor as an editorial judgement about whether motion is useful at that size, and the reduced-motion query as a hard constraint that must be able to remove motion the container query allowed.",[14,1557,1558,1561],{},[1546,1559,1560],{},"How do I stop the suppressed version from feeling broken?","\nKeep the state change and remove only the movement. Swap the animated property for an instant one such as a border, background, or opacity step so hover, focus, and open states are still visibly acknowledged without travel.",[14,1563,1564,1567,1568,1570],{},[1546,1565,1566],{},"Is animation: none enough to suppress an animation?","\nIt removes the animation but leaves the element wherever its base styles put it, which may be an entrance start state such as ",[40,1569,1103],{},". Reset those properties in the same rule so the element renders in its final position rather than its hidden one.",[29,1572],{},[32,1574,1576],{"id":1575},"related","Related",[1578,1579,1580,1587,1593,1600,1607],"ul",{},[1581,1582,1583,1586],"li",{},[18,1584,1585],{"href":20},"Container-Aware Motion"," — the parent section covering the whole approach.",[1581,1588,1589,1592],{},[18,1590,1591],{"href":25},"Motion That Scales with Container Size"," — proportional travel, which this page bounds from below.",[1581,1594,1595,1599],{},[18,1596,1598],{"href":1597},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances\u002F","Container Query Hover Affordances"," — the sibling case where the affordance changes rather than the motion.",[1581,1601,1602,1606],{},[18,1603,1605],{"href":1604},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Freducing-motion-preferences-in-css\u002F","Reducing Motion Preferences in CSS"," — the preference layer that overrides every container decision.",[1581,1608,1609,1613],{},[18,1610,1612],{"href":1611},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002F","Container Query Syntax Basics"," — the cross-area reference for the query mechanics used here.",[1615,1616,1617],"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 .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 .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .sh5d0, html code.shiki .sh5d0{--shiki-default:#6E011A;--shiki-default-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic}",{"title":182,"searchDepth":213,"depth":213,"links":1619},[1620,1621,1622,1623,1624,1625,1626,1627],{"id":34,"depth":213,"text":35},{"id":62,"depth":213,"text":63},{"id":1060,"depth":213,"text":1061},{"id":1183,"depth":213,"text":1184},{"id":1496,"depth":213,"text":1497},{"id":1518,"depth":213,"text":1519},{"id":1541,"depth":213,"text":1542},{"id":1575,"depth":213,"text":1576},"Switch animation off below a container width floor with @container, layer it under prefers-reduced-motion, and keep the still version feeling finished.","md",{"pageTitle":1631,"datePublished":1632,"dateModified":1632,"faq":1633},"Suppressing Motion in Small Containers","2026-07-20",[1634,1636,1638,1640],{"q":1548,"a":1635},"The travel distance shrinks with the box until it is only a few pixels, and a few pixels of movement over a few hundred milliseconds is below the threshold at which the eye reads direction. Without a perceived direction the movement registers as instability or a rendering fault rather than a transition.",{"q":1554,"a":1637},"The user preference always wins. Treat the container floor as an editorial judgement about whether motion is useful at that size, and the reduced-motion query as a hard constraint that must be able to remove motion the container query allowed.",{"q":1560,"a":1639},"Keep the state change and remove only the movement. Swap the animated property for an instant one such as a border, background, or opacity step so hover, focus, and open states are still visibly acknowledged without travel.",{"q":1566,"a":1641},"It removes the animation but leaves the element wherever its base styles put it, which may be an entrance start state such as opacity zero. Reset those properties in the same rule so the element renders in its final position rather than its hidden one.","\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers",{"title":5,"description":1628},"css-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers\u002Findex","swB8XdnxF-Gypbv84fllZCHYCJsFBGtB-AIRUIAlFwo",[1647,1650,1653,1656,1659,1662,1665,1668,1671,1674,1677,1678,1681,1684,1687,1690,1693,1696,1699,1702,1705,1708,1711,1714,1717,1720,1723,1726,1729,1732,1735,1738,1741,1744,1747,1750,1753,1756,1759,1762,1765,1768,1771,1774,1777,1780,1783,1786,1789,1792,1795,1798,1801,1804,1807,1810,1813,1816,1819,1821,1824,1827,1830,1833,1836,1839,1842,1845,1848,1851,1854,1857,1860,1863,1866,1869,1872,1875,1878,1881,1884,1887,1890,1893,1896,1899,1902,1905],{"path":1648,"title":1649},"\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":1651,"title":1652},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1654,"title":1655},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1657,"title":1658},"\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":1660,"title":1661},"\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":1663,"title":1664},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1666,"title":1667},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1669,"title":1670},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1672,"title":1673},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1675,"title":1676},"\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":1642,"title":5},{"path":1679,"title":1680},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1682,"title":1683},"\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":1685,"title":1686},"\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":1688,"title":1689},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1691,"title":1692},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1694,"title":1695},"\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":1697,"title":1698},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1700,"title":1701},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1703,"title":1704},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1706,"title":1707},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1709,"title":1710},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1712,"title":1713},"\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":1715,"title":1716},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1718,"title":1719},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1721,"title":1722},"\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":1724,"title":1725},"\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":1727,"title":1728},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1730,"title":1731},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1733,"title":1734},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1736,"title":1737},"\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":1739,"title":1740},"\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":1742,"title":1743},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1745,"title":1746},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1748,"title":1749},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1751,"title":1752},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1754,"title":1755},"\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":1757,"title":1758},"\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":1760,"title":1761},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1763,"title":1764},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1766,"title":1767},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1769,"title":1770},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1772,"title":1773},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1775,"title":1776},"\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":1778,"title":1779},"\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":1781,"title":1782},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":1784,"title":1785},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":1787,"title":1788},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1790,"title":1791},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1793,"title":1794},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1796,"title":1797},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1799,"title":1800},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1802,"title":1803},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1805,"title":1806},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1808,"title":1809},"\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":1811,"title":1812},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1814,"title":1815},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1817,"title":1818},"\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":1820,"title":1612},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics",{"path":1822,"title":1823},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1825,"title":1826},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1828,"title":1829},"\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":1831,"title":1832},"\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":1834,"title":1835},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1837,"title":1838},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1840,"title":1841},"\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":1843,"title":1844},"\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":1846,"title":1847},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1849,"title":1850},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1852,"title":1853},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1855,"title":1856},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1858,"title":1859},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1861,"title":1862},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1864,"title":1865},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1867,"title":1868},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1870,"title":1871},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1873,"title":1874},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1876,"title":1877},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1879,"title":1880},"\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":1882,"title":1883},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1885,"title":1886},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":1888,"title":1889},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":1891,"title":1892},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":1894,"title":1895},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":1897,"title":1898},"\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":1900,"title":1901},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":1903,"title":1904},"\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":1906,"title":1907},"\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",1784566157489]