[{"data":1,"prerenderedAt":2089},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries":3,"content-all-pages":1525,"live-demo:style-query-motion":2083},{"id":4,"title":5,"body":6,"description":1508,"extension":1509,"meta":1510,"navigation":353,"path":1521,"seo":1522,"stem":1523,"__hash__":1524},"content\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries\u002Findex.md","Motion Driven by Container Style Queries",{"type":7,"value":8,"toc":1494},"minimark",[9,13,41,46,57,149,153,167,171,1137,1168,1172,1185,1265,1284,1288,1298,1302,1334,1338,1352,1356,1367,1375,1392,1396,1410,1414,1427,1433,1447,1457,1461,1491],[10,11,5],"h1",{"id":12},"motion-driven-by-container-style-queries",[14,15,16,17,21,22,25,26,29,30,35,36,40],"p",{},"Components often move through states — idle, loading, success, error — and each state has its own motion: a spinner while loading, a small bounce on success, a shake on error. The usual approach is a state class on the component and a matching selector for every animated part: ",[18,19,20],"code",{},".upload.is-loading .upload__icon",", ",[18,23,24],{},".upload.is-error .upload__field",", and so on. Container style queries offer a cleaner wiring. Set one custom property on the container — ",[18,27,28],{},"--state: loading"," — and let each descendant query it. The parts do not need to know about the component's classes, only about the state vocabulary. This page builds a state-driven upload button with style queries and covers how to keep the motion accessible and the fallback sensible. It belongs to ",[31,32,34],"a",{"href":33},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002F","Container-Aware Motion"," in the ",[31,37,39],{"href":38},"\u002Fcss-only-micro-interactions-animations\u002F","CSS-Only Micro-Interactions & Animations"," guide.",[42,43,45],"h2",{"id":44},"how-style-queries-select-motion","How style queries select motion",[14,47,48,49,52,53,56],{},"A container style query tests the computed value of a custom property on an ancestor: ",[18,50,51],{},"@container style(--state: loading) { … }",". Rules inside apply to descendants whenever the condition holds. Because the query reads a computed value, it does not matter how the property got there — an inline style, a class, ",[18,54,55],{},":has()",", or a parent's inheritance all work. Any animation property can be set inside the block, so the state picks the animation.",[58,59,65,66,65,70,65,74,65,82,65,89,65,94,65,103,65,106,65,109,65,115,65,120,65,123,65,126,65,130,65,133,65,139,65,141,65,144],"svg",{"viewBox":60,"role":61,"ariaLabel":62,"xmlns":63,"style":64},"0 0 720 300","img","One custom property on a container selects the motion of three descendants: an icon, a label and a progress track, each querying the state","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[67,68,69],"title",{},"One property, many reactions",[71,72,73],"desc",{},"A container box with --state set to loading. Inside it, three child boxes: the icon, which spins when the state is loading; the label, which pulses gently; and the track, which shows an indeterminate sweep. Arrows from the container's property to each child are labelled with the style query that matches.",[75,76,81],"text",{"textAnchor":77,"x":78,"y":79,"style":80},"middle","360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","The container announces; descendants react",[83,84],"path",{"d":85,"fill":86,"opacity":87,"stroke":86,"strokeWidth":88},"M60 50 H660 V270 H60 Z","#7aa2ff","0.12","1.5",[75,90,93],{"textAnchor":77,"x":78,"y":91,"style":92},"80","text-anchor:middle;fill:currentColor;font:600 14px ui-monospace,monospace",".upload { --state: loading }",[95,96],"rect",{"x":97,"y":98,"width":99,"height":91,"rx":100,"fill":101,"stroke":102,"strokeWidth":88},"90","150","160","8","none","currentColor",[95,104],{"x":105,"y":98,"width":99,"height":91,"rx":100,"fill":101,"stroke":102,"strokeWidth":88},"280",[95,107],{"x":108,"y":98,"width":99,"height":91,"rx":100,"fill":101,"stroke":102,"strokeWidth":88},"470",[75,110,114],{"textAnchor":77,"x":111,"y":112,"style":113},"170","184","text-anchor:middle;fill:currentColor;font:600 13px sans-serif","icon",[75,116,119],{"textAnchor":77,"x":111,"y":117,"style":118},"206","text-anchor:middle;fill:currentColor;font:12px sans-serif","spins",[75,121,122],{"textAnchor":77,"x":78,"y":112,"style":113},"label",[75,124,125],{"textAnchor":77,"x":78,"y":117,"style":118},"fades gently",[75,127,129],{"textAnchor":77,"x":128,"y":112,"style":113},"550","track",[75,131,132],{"textAnchor":77,"x":128,"y":117,"style":118},"sweeps",[134,135],"line",{"x1":136,"y1":137,"x2":111,"y2":98,"stroke":102,"strokeWidth":88,"opacity":138},"300","92","0.6",[134,140],{"x1":78,"y1":137,"x2":78,"y2":98,"stroke":102,"strokeWidth":88,"opacity":138},[134,142],{"x1":143,"y1":137,"x2":128,"y2":98,"stroke":102,"strokeWidth":88,"opacity":138},"420",[75,145,148],{"textAnchor":77,"x":78,"y":146,"style":147},"256","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","@container style(--state: loading)",[42,150,152],{"id":151},"the-complete-implementation","The complete implementation",[14,154,155,156,158,159,162,163,166],{},"The demo drives the state with radio buttons and ",[18,157,55],{},", so it runs without script. In an application, script would set ",[18,160,161],{},"--state"," directly, for example ",[18,164,165],{},"el.style.setProperty('--state', 'success')",".",[168,169],"live-demo",{"name":170},"style-query-motion",[172,173,178],"pre",{"className":174,"code":175,"language":176,"meta":177,"style":177},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003C!doctype html>\n\u003Chtml lang=\"en\">\n\u003Chead>\n\u003Cmeta charset=\"utf-8\">\n\u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\u003Ctitle>Style-query motion states\u003C\u002Ftitle>\n\u003Cstyle>\n  body { font: 15px\u002F1.5 system-ui, sans-serif; margin: 2rem; }\n\n  .upload {\n    container-name: upload;\n    --state: idle;\n    display: flex;\n    align-items: center;\n    gap: 0.75rem;\n    padding: 0.75rem 1rem;\n    border: 1px solid #cbd5e1;\n    border-radius: 10px;\n    inline-size: fit-content;\n  }\n\n  .upload__icon {\n    inline-size: 1.25rem;\n    aspect-ratio: 1;\n    border-radius: 50%;\n    border: 3px solid #94a3b8;\n  }\n\n  \u002F* State-specific motion, chosen by the container's --state. *\u002F\n  @container upload style(--state: loading) {\n    .upload__icon {\n      border-color: #2563eb #2563eb transparent transparent;\n      animation: spin 800ms linear infinite;\n    }\n  }\n  @container upload style(--state: success) {\n    .upload__icon {\n      border-color: #16a34a;\n      background: #16a34a;\n      animation: pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1);\n    }\n  }\n  @container upload style(--state: error) {\n    .upload__icon {\n      border-color: #dc2626;\n      animation: shake 360ms ease-in-out;\n    }\n  }\n\n  @keyframes spin  { to { rotate: 1turn; } }\n  @keyframes pop   { from { scale: 0.6; } }\n  @keyframes shake {\n    25% { translate: -4px 0; }\n    50% { translate: 4px 0; }\n    75% { translate: -2px 0; }\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    .upload__icon { animation-duration: 1ms !important; animation-iteration-count: 1 !important; }\n  }\n\u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Cdiv class=\"upload\" style=\"--state: loading\">\n    \u003Cspan class=\"upload__icon\" aria-hidden=\"true\">\u003C\u002Fspan>\n    \u003Cspan class=\"upload__label\" role=\"status\">Uploading…\u003C\u002Fspan>\n  \u003C\u002Fdiv>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html","",[18,179,180,199,219,229,247,272,286,296,348,355,364,373,383,397,410,425,444,465,480,493,499,504,512,526,538,553,572,577,582,589,598,606,627,650,656,661,669,676,688,700,739,744,749,757,764,776,793,798,803,808,838,863,873,896,917,938,943,948,957,989,994,1004,1013,1023,1050,1080,1109,1119,1128],{"__ignoreMap":177},[181,182,184,188,192,196],"span",{"class":134,"line":183},1,[181,185,187],{"class":186},"suds8","\u003C!",[181,189,191],{"class":190},"sne4z","doctype",[181,193,195],{"class":194},"s-5SL"," html",[181,197,198],{"class":186},">\n",[181,200,202,205,207,210,213,217],{"class":134,"line":201},2,[181,203,204],{"class":186},"\u003C",[181,206,176],{"class":190},[181,208,209],{"class":194}," lang",[181,211,212],{"class":186},"=",[181,214,216],{"class":215},"sT6z2","\"en\"",[181,218,198],{"class":186},[181,220,222,224,227],{"class":134,"line":221},3,[181,223,204],{"class":186},[181,225,226],{"class":190},"head",[181,228,198],{"class":186},[181,230,232,234,237,240,242,245],{"class":134,"line":231},4,[181,233,204],{"class":186},[181,235,236],{"class":190},"meta",[181,238,239],{"class":194}," charset",[181,241,212],{"class":186},[181,243,244],{"class":215},"\"utf-8\"",[181,246,198],{"class":186},[181,248,250,252,254,257,259,262,265,267,270],{"class":134,"line":249},5,[181,251,204],{"class":186},[181,253,236],{"class":190},[181,255,256],{"class":194}," name",[181,258,212],{"class":186},[181,260,261],{"class":215},"\"viewport\"",[181,263,264],{"class":194}," content",[181,266,212],{"class":186},[181,268,269],{"class":215},"\"width=device-width, initial-scale=1\"",[181,271,198],{"class":186},[181,273,275,277,279,282,284],{"class":134,"line":274},6,[181,276,204],{"class":186},[181,278,67],{"class":190},[181,280,281],{"class":186},">Style-query motion states\u003C\u002F",[181,283,67],{"class":190},[181,285,198],{"class":186},[181,287,289,291,294],{"class":134,"line":288},7,[181,290,204],{"class":186},[181,292,293],{"class":190},"style",[181,295,198],{"class":186},[181,297,299,302,305,308,311,314,318,321,323,326,328,331,334,337,339,342,345],{"class":134,"line":298},8,[181,300,301],{"class":190},"  body",[181,303,304],{"class":186}," { ",[181,306,307],{"class":194},"font",[181,309,310],{"class":186},": ",[181,312,313],{"class":194},"15",[181,315,317],{"class":316},"sHUrx","px",[181,319,320],{"class":186},"\u002F",[181,322,88],{"class":194},[181,324,325],{"class":194}," system-ui",[181,327,21],{"class":186},[181,329,330],{"class":194},"sans-serif",[181,332,333],{"class":186},"; ",[181,335,336],{"class":194},"margin",[181,338,310],{"class":186},[181,340,341],{"class":194},"2",[181,343,344],{"class":316},"rem",[181,346,347],{"class":186},"; }\n",[181,349,351],{"class":134,"line":350},9,[181,352,354],{"emptyLinePlaceholder":353},true,"\n",[181,356,358,361],{"class":134,"line":357},10,[181,359,360],{"class":194},"  .upload",[181,362,363],{"class":186}," {\n",[181,365,367,370],{"class":134,"line":366},11,[181,368,369],{"class":194},"    container-name",[181,371,372],{"class":186},": upload;\n",[181,374,376,380],{"class":134,"line":375},12,[181,377,379],{"class":378},"soyes","    --state",[181,381,382],{"class":186},": idle;\n",[181,384,386,389,391,394],{"class":134,"line":385},13,[181,387,388],{"class":194},"    display",[181,390,310],{"class":186},[181,392,393],{"class":194},"flex",[181,395,396],{"class":186},";\n",[181,398,400,403,405,408],{"class":134,"line":399},14,[181,401,402],{"class":194},"    align-items",[181,404,310],{"class":186},[181,406,407],{"class":194},"center",[181,409,396],{"class":186},[181,411,413,416,418,421,423],{"class":134,"line":412},15,[181,414,415],{"class":194},"    gap",[181,417,310],{"class":186},[181,419,420],{"class":194},"0.75",[181,422,344],{"class":316},[181,424,396],{"class":186},[181,426,428,431,433,435,437,440,442],{"class":134,"line":427},16,[181,429,430],{"class":194},"    padding",[181,432,310],{"class":186},[181,434,420],{"class":194},[181,436,344],{"class":316},[181,438,439],{"class":194}," 1",[181,441,344],{"class":316},[181,443,396],{"class":186},[181,445,447,450,452,455,457,460,463],{"class":134,"line":446},17,[181,448,449],{"class":194},"    border",[181,451,310],{"class":186},[181,453,454],{"class":194},"1",[181,456,317],{"class":316},[181,458,459],{"class":194}," solid",[181,461,462],{"class":194}," #cbd5e1",[181,464,396],{"class":186},[181,466,468,471,473,476,478],{"class":134,"line":467},18,[181,469,470],{"class":194},"    border-radius",[181,472,310],{"class":186},[181,474,475],{"class":194},"10",[181,477,317],{"class":316},[181,479,396],{"class":186},[181,481,483,486,488,491],{"class":134,"line":482},19,[181,484,485],{"class":194},"    inline-size",[181,487,310],{"class":186},[181,489,490],{"class":194},"fit-content",[181,492,396],{"class":186},[181,494,496],{"class":134,"line":495},20,[181,497,498],{"class":186},"  }\n",[181,500,502],{"class":134,"line":501},21,[181,503,354],{"emptyLinePlaceholder":353},[181,505,507,510],{"class":134,"line":506},22,[181,508,509],{"class":194},"  .upload__icon",[181,511,363],{"class":186},[181,513,515,517,519,522,524],{"class":134,"line":514},23,[181,516,485],{"class":194},[181,518,310],{"class":186},[181,520,521],{"class":194},"1.25",[181,523,344],{"class":316},[181,525,396],{"class":186},[181,527,529,532,534,536],{"class":134,"line":528},24,[181,530,531],{"class":194},"    aspect-ratio",[181,533,310],{"class":186},[181,535,454],{"class":194},[181,537,396],{"class":186},[181,539,541,543,545,548,551],{"class":134,"line":540},25,[181,542,470],{"class":194},[181,544,310],{"class":186},[181,546,547],{"class":194},"50",[181,549,550],{"class":316},"%",[181,552,396],{"class":186},[181,554,556,558,560,563,565,567,570],{"class":134,"line":555},26,[181,557,449],{"class":194},[181,559,310],{"class":186},[181,561,562],{"class":194},"3",[181,564,317],{"class":316},[181,566,459],{"class":194},[181,568,569],{"class":194}," #94a3b8",[181,571,396],{"class":186},[181,573,575],{"class":134,"line":574},27,[181,576,498],{"class":186},[181,578,580],{"class":134,"line":579},28,[181,581,354],{"emptyLinePlaceholder":353},[181,583,585],{"class":134,"line":584},29,[181,586,588],{"class":587},"sLBg1","  \u002F* State-specific motion, chosen by the container's --state. *\u002F\n",[181,590,592,595],{"class":134,"line":591},30,[181,593,594],{"class":316},"  @container",[181,596,597],{"class":186}," upload style(--state: loading) {\n",[181,599,601,604],{"class":134,"line":600},31,[181,602,603],{"class":194},"    .upload__icon",[181,605,363],{"class":186},[181,607,609,612,614,617,620,623,625],{"class":134,"line":608},32,[181,610,611],{"class":194},"      border-color",[181,613,310],{"class":186},[181,615,616],{"class":194},"#2563eb",[181,618,619],{"class":194}," #2563eb",[181,621,622],{"class":194}," transparent",[181,624,622],{"class":194},[181,626,396],{"class":186},[181,628,630,633,636,639,642,645,648],{"class":134,"line":629},33,[181,631,632],{"class":194},"      animation",[181,634,635],{"class":186},": spin ",[181,637,638],{"class":194},"800",[181,640,641],{"class":316},"ms",[181,643,644],{"class":194}," linear",[181,646,647],{"class":194}," infinite",[181,649,396],{"class":186},[181,651,653],{"class":134,"line":652},34,[181,654,655],{"class":186},"    }\n",[181,657,659],{"class":134,"line":658},35,[181,660,498],{"class":186},[181,662,664,666],{"class":134,"line":663},36,[181,665,594],{"class":316},[181,667,668],{"class":186}," upload style(--state: success) {\n",[181,670,672,674],{"class":134,"line":671},37,[181,673,603],{"class":194},[181,675,363],{"class":186},[181,677,679,681,683,686],{"class":134,"line":678},38,[181,680,611],{"class":194},[181,682,310],{"class":186},[181,684,685],{"class":194},"#16a34a",[181,687,396],{"class":186},[181,689,691,694,696,698],{"class":134,"line":690},39,[181,692,693],{"class":194},"      background",[181,695,310],{"class":186},[181,697,685],{"class":194},[181,699,396],{"class":186},[181,701,703,705,708,711,713,716,719,722,724,727,729,732,734,736],{"class":134,"line":702},40,[181,704,632],{"class":194},[181,706,707],{"class":186},": pop ",[181,709,710],{"class":194},"320",[181,712,641],{"class":316},[181,714,715],{"class":194}," cubic-bezier",[181,717,718],{"class":186},"(",[181,720,721],{"class":194},"0.34",[181,723,21],{"class":186},[181,725,726],{"class":194},"1.56",[181,728,21],{"class":186},[181,730,731],{"class":194},"0.64",[181,733,21],{"class":186},[181,735,454],{"class":194},[181,737,738],{"class":186},");\n",[181,740,742],{"class":134,"line":741},41,[181,743,655],{"class":186},[181,745,747],{"class":134,"line":746},42,[181,748,498],{"class":186},[181,750,752,754],{"class":134,"line":751},43,[181,753,594],{"class":316},[181,755,756],{"class":186}," upload style(--state: error) {\n",[181,758,760,762],{"class":134,"line":759},44,[181,761,603],{"class":194},[181,763,363],{"class":186},[181,765,767,769,771,774],{"class":134,"line":766},45,[181,768,611],{"class":194},[181,770,310],{"class":186},[181,772,773],{"class":194},"#dc2626",[181,775,396],{"class":186},[181,777,779,781,784,786,788,791],{"class":134,"line":778},46,[181,780,632],{"class":194},[181,782,783],{"class":186},": shake ",[181,785,78],{"class":194},[181,787,641],{"class":316},[181,789,790],{"class":194}," ease-in-out",[181,792,396],{"class":186},[181,794,796],{"class":134,"line":795},47,[181,797,655],{"class":186},[181,799,801],{"class":134,"line":800},48,[181,802,498],{"class":186},[181,804,806],{"class":134,"line":805},49,[181,807,354],{"emptyLinePlaceholder":353},[181,809,811,814,817,820,823,825,828,830,832,835],{"class":134,"line":810},50,[181,812,813],{"class":316},"  @keyframes",[181,815,816],{"class":378}," spin",[181,818,819],{"class":186},"  { ",[181,821,822],{"class":194},"to",[181,824,304],{"class":186},[181,826,827],{"class":194},"rotate",[181,829,310],{"class":186},[181,831,454],{"class":194},[181,833,834],{"class":316},"turn",[181,836,837],{"class":186},"; } }\n",[181,839,841,843,846,849,852,854,857,859,861],{"class":134,"line":840},51,[181,842,813],{"class":316},[181,844,845],{"class":378}," pop",[181,847,848],{"class":186},"   { ",[181,850,851],{"class":194},"from",[181,853,304],{"class":186},[181,855,856],{"class":194},"scale",[181,858,310],{"class":186},[181,860,138],{"class":194},[181,862,837],{"class":186},[181,864,866,868,871],{"class":134,"line":865},52,[181,867,813],{"class":316},[181,869,870],{"class":378}," shake",[181,872,363],{"class":186},[181,874,876,879,881,884,886,889,891,894],{"class":134,"line":875},53,[181,877,878],{"class":194},"    25%",[181,880,304],{"class":186},[181,882,883],{"class":194},"translate",[181,885,310],{"class":186},[181,887,888],{"class":194},"-4",[181,890,317],{"class":316},[181,892,893],{"class":194}," 0",[181,895,347],{"class":186},[181,897,899,902,904,906,908,911,913,915],{"class":134,"line":898},54,[181,900,901],{"class":194},"    50%",[181,903,304],{"class":186},[181,905,883],{"class":194},[181,907,310],{"class":186},[181,909,910],{"class":194},"4",[181,912,317],{"class":316},[181,914,893],{"class":194},[181,916,347],{"class":186},[181,918,920,923,925,927,929,932,934,936],{"class":134,"line":919},55,[181,921,922],{"class":194},"    75%",[181,924,304],{"class":186},[181,926,883],{"class":194},[181,928,310],{"class":186},[181,930,931],{"class":194},"-2",[181,933,317],{"class":316},[181,935,893],{"class":194},[181,937,347],{"class":186},[181,939,941],{"class":134,"line":940},56,[181,942,498],{"class":186},[181,944,946],{"class":134,"line":945},57,[181,947,354],{"emptyLinePlaceholder":353},[181,949,951,954],{"class":134,"line":950},58,[181,952,953],{"class":316},"  @media",[181,955,956],{"class":186}," (prefers-reduced-motion: reduce) {\n",[181,958,960,962,964,967,969,971,973,976,978,981,983,985,987],{"class":134,"line":959},59,[181,961,603],{"class":194},[181,963,304],{"class":186},[181,965,966],{"class":194},"animation-duration",[181,968,310],{"class":186},[181,970,454],{"class":194},[181,972,641],{"class":316},[181,974,975],{"class":316}," !important",[181,977,333],{"class":186},[181,979,980],{"class":194},"animation-iteration-count",[181,982,310],{"class":186},[181,984,454],{"class":194},[181,986,975],{"class":316},[181,988,347],{"class":186},[181,990,992],{"class":134,"line":991},60,[181,993,498],{"class":186},[181,995,997,1000,1002],{"class":134,"line":996},61,[181,998,999],{"class":186},"\u003C\u002F",[181,1001,293],{"class":190},[181,1003,198],{"class":186},[181,1005,1007,1009,1011],{"class":134,"line":1006},62,[181,1008,999],{"class":186},[181,1010,226],{"class":190},[181,1012,198],{"class":186},[181,1014,1016,1018,1021],{"class":134,"line":1015},63,[181,1017,204],{"class":186},[181,1019,1020],{"class":190},"body",[181,1022,198],{"class":186},[181,1024,1026,1029,1032,1035,1037,1040,1043,1045,1048],{"class":134,"line":1025},64,[181,1027,1028],{"class":186},"  \u003C",[181,1030,1031],{"class":190},"div",[181,1033,1034],{"class":194}," class",[181,1036,212],{"class":186},[181,1038,1039],{"class":215},"\"upload\"",[181,1041,1042],{"class":194}," style",[181,1044,212],{"class":186},[181,1046,1047],{"class":215},"\"--state: loading\"",[181,1049,198],{"class":186},[181,1051,1053,1056,1058,1060,1062,1065,1068,1070,1073,1076,1078],{"class":134,"line":1052},65,[181,1054,1055],{"class":186},"    \u003C",[181,1057,181],{"class":190},[181,1059,1034],{"class":194},[181,1061,212],{"class":186},[181,1063,1064],{"class":215},"\"upload__icon\"",[181,1066,1067],{"class":194}," aria-hidden",[181,1069,212],{"class":186},[181,1071,1072],{"class":215},"\"true\"",[181,1074,1075],{"class":186},">\u003C\u002F",[181,1077,181],{"class":190},[181,1079,198],{"class":186},[181,1081,1083,1085,1087,1089,1091,1094,1097,1099,1102,1105,1107],{"class":134,"line":1082},66,[181,1084,1055],{"class":186},[181,1086,181],{"class":190},[181,1088,1034],{"class":194},[181,1090,212],{"class":186},[181,1092,1093],{"class":215},"\"upload__label\"",[181,1095,1096],{"class":194}," role",[181,1098,212],{"class":186},[181,1100,1101],{"class":215},"\"status\"",[181,1103,1104],{"class":186},">Uploading…\u003C\u002F",[181,1106,181],{"class":190},[181,1108,198],{"class":186},[181,1110,1112,1115,1117],{"class":134,"line":1111},67,[181,1113,1114],{"class":186},"  \u003C\u002F",[181,1116,1031],{"class":190},[181,1118,198],{"class":186},[181,1120,1122,1124,1126],{"class":134,"line":1121},68,[181,1123,999],{"class":186},[181,1125,1020],{"class":190},[181,1127,198],{"class":186},[181,1129,1131,1133,1135],{"class":134,"line":1130},69,[181,1132,999],{"class":186},[181,1134,176],{"class":190},[181,1136,198],{"class":186},[14,1138,1139,1140,1142,1143,1146,1147,1150,1151,1154,1155,1157,1158,1161,1162,1164,1165,166],{},"Each state's block sets both the static look (border colour, fill) and the motion (the animation). Switching ",[18,1141,161],{}," from ",[18,1144,1145],{},"loading"," to ",[18,1148,1149],{},"success"," stops the spin, because the loading block no longer matches, and starts the pop, because a new ",[18,1152,1153],{},"animation-name"," applies. Changing ",[18,1156,1153],{}," always starts the new animation from its beginning, which is exactly right for one-off state feedback. It also means that setting the same state twice in a row does nothing: re-applying ",[18,1159,1160],{},"--state: error"," after an error does not replay the shake, because the computed ",[18,1163,1153],{}," never changed. If repeated errors should each shake, toggle through another state, or restart the animation from script with ",[18,1166,1167],{},"getAnimations()",[42,1169,1171],{"id":1170},"the-key-technique-the-state-vocabulary-is-the-api","The key technique: the state vocabulary is the API",[14,1173,1174,1175,1177,1178,1181,1182,1184],{},"The component's parts depend only on the values ",[18,1176,161],{}," can take, not on class names or DOM structure. That makes the vocabulary the contract. Document it — ",[18,1179,1180],{},"idle | loading | success | error"," — and keep it small. New parts can join the component and react to the same states without touching the component's root; a parent component can even set ",[18,1183,161],{}," on a child's container to drive it, without reaching into its internals.",[58,1186,65,1189,65,1192,65,1195,65,1198,65,1203,65,1207,65,1213,65,1215,65,1220,65,1222,65,1225,65,1229,65,1233,65,1239,65,1243,65,1250,65,1254,65,1258,65,1261],{"viewBox":1187,"role":61,"ariaLabel":1188,"xmlns":63,"style":64},"0 0 720 250","A state machine with four states, idle, loading, success and error, each associated with a motion: none, a spin, a pop and a shake",[67,1190,1191],{},"Four states, four motions",[71,1193,1194],{},"Four circles in a row labelled idle, loading, success and error. Arrows go from idle to loading, and from loading to success and to error. Under each state is its motion: idle has none, loading has an infinite spin, success has a one-off pop, error has a one-off shake.",[75,1196,1197],{"textAnchor":77,"x":78,"y":79,"style":80},"The --state vocabulary",[1199,1200],"circle",{"cx":1201,"cy":1201,"r":1202,"fill":101,"stroke":102,"strokeWidth":88},"110","46",[1199,1204],{"cx":1205,"cy":1201,"r":1202,"fill":86,"opacity":1206},"290","0.3",[1199,1208],{"cx":1209,"cy":1210,"r":1211,"fill":86,"opacity":1212},"490","70","40","0.2",[1199,1214],{"cx":1209,"cy":111,"r":1211,"fill":102,"opacity":87},[75,1216,1219],{"textAnchor":77,"x":1201,"y":1217,"style":1218},"115","text-anchor:middle;fill:currentColor;font:600 13px ui-monospace,monospace","idle",[75,1221,1145],{"textAnchor":77,"x":1205,"y":1217,"style":1218},[75,1223,1149],{"textAnchor":77,"x":1209,"y":1224,"style":1218},"75",[75,1226,1228],{"textAnchor":77,"x":1209,"y":1227,"style":1218},"175","error",[134,1230],{"x1":1231,"y1":1201,"x2":1232,"y2":1201,"stroke":102,"strokeWidth":88},"156","244",[134,1234],{"x1":1235,"y1":1236,"x2":1237,"y2":1238,"stroke":102,"strokeWidth":88},"334","96","452","76",[134,1240],{"x1":1235,"y1":1241,"x2":1237,"y2":1242,"stroke":102,"strokeWidth":88},"124","164",[75,1244,1249],{"textAnchor":1245,"x":1246,"y":1247,"style":1248},"start","560","74","text-anchor:start;fill:currentColor;font:12px sans-serif","pop once",[75,1251,1253],{"textAnchor":1245,"x":1246,"y":1252,"style":1248},"174","shake once",[75,1255,1257],{"textAnchor":77,"x":1201,"y":1256,"style":118},"182","no motion",[75,1259,1260],{"textAnchor":77,"x":1205,"y":1256,"style":118},"spin, infinite",[75,1262,1264],{"textAnchor":77,"x":78,"y":1263,"style":118},"236","Only loading loops; feedback states play once and stop.",[14,1266,1267,1268,1271,1272,1275,1276,1278,1279,1283],{},"Registering the property tightens the contract further. ",[18,1269,1270],{},"@property --state { syntax: \"idle | loading | success | error\"; inherits: true; initial-value: idle; }"," rejects any other value, so a typo such as ",[18,1273,1274],{},"--state: sucess"," falls back to ",[18,1277,1219],{}," instead of silently matching nothing. ",[31,1280,1282],{"href":1281},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fregistered-properties-and-type-safety\u002F","Registered Properties and Type Safety"," covers keyword syntax strings.",[42,1285,1287],{"id":1286},"smoothing-the-static-changes-between-states","Smoothing the static changes between states",[14,1289,1290,1291,1146,1294,1297],{},"The keyframe animations handle the motion, but each state also changes static properties — the icon's border colour and fill. Those change instantly unless they are transitioned. Adding ",[18,1292,1293],{},"transition: border-color 200ms ease-out, background-color 200ms ease-out",[18,1295,1296],{},".upload__icon",", outside the style-query blocks, lets colours cross-fade as the state changes while the keyframes play on top. The two mechanisms cooperate: transitions smooth the values that persist in a state, and animations add the one-off or looping motion that marks entering it.",[42,1299,1301],{"id":1300},"watch-out-for-inherited-state-in-nested-components","Watch out for inherited state in nested components",[14,1303,1304,1306,1307,1309,1310,1314,1315,21,1318,1321,1322,1325,1326,1329,1330,1333],{},[18,1305,161],{}," inherits, which is the point — every descendant can see it. It also means a nested component that uses the same property name sees its ancestor's state. An upload button inside a form whose container is ",[18,1308,1160],{}," would start shaking along with the form. Two remedies from ",[31,1311,1313],{"href":1312},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components\u002F","Scoping Custom Properties to Components"," apply directly. Either prefix the property per component (",[18,1316,1317],{},"--upload-state",[18,1319,1320],{},"--form-state","), or reset it at each component root with a zero-specificity rule such as ",[18,1323,1324],{},":where(.upload) { --state: idle; }"," so every component starts from its own idle state. Naming the container helps too: ",[18,1327,1328],{},"@container upload style(...)"," only ever tests the nearest ",[18,1331,1332],{},"upload"," container, not whichever ancestor happens to be closest.",[42,1335,1337],{"id":1336},"debugging-style-queries","Debugging style queries",[14,1339,1340,1341,1343,1344,1347,1348,1351],{},"When a state's motion does not appear, check three things in order. First, confirm the custom property's computed value on the container in DevTools' Computed pane — a stray space or quote makes ",[18,1342,1145],{}," and ",[18,1345,1346],{},"\"loading\""," different values. Second, confirm the query targets the right container: an unnamed style query tests the nearest ancestor, which may be an intermediate wrapper rather than the component root. Third, check that the animation property is not overridden by a more specific rule outside the query, since rules inside ",[18,1349,1350],{},"@container"," have no extra specificity of their own.",[42,1353,1355],{"id":1354},"accessibility-of-state-motion","Accessibility of state motion",[14,1357,1358,1359,1362,1363,1366],{},"Motion reinforces the state but must not be its only signal. The implementation pairs every animation with a static change — border colour, fill — and the label, marked ",[18,1360,1361],{},"role=\"status\"",", announces the new state to screen readers when script updates its text. The shake for errors is small (4 pixels) and runs once, which keeps it clear of vestibular triggers; a larger or repeating shake would not be. Under ",[18,1364,1365],{},"prefers-reduced-motion: reduce",", the implementation collapses every state animation to a single 1ms iteration, so the end-state styling still applies while the movement disappears. The spinner is the one exception worth considering: an infinitely looping spinner for a long upload should also offer a text progress indication, since WCAG 2.2.2 asks for a way to pause motion that lasts more than five seconds.",[42,1368,1370,1371,1374],{"id":1369},"style-queries-versus-classes-and","Style queries versus classes and ",[1372,1373],"has",{},"()",[14,1376,1377,1378,1380,1381,1384,1385,1391],{},"Style queries are not always the right tool. A class on the component is simpler when only one or two parts animate and they are always in the same place. ",[18,1379,55],{}," is better when the state is already expressed in the DOM — an ",[18,1382,1383],{},"aria-busy=\"true\""," attribute, a checked input — because it avoids duplicating that state in a custom property. Style queries shine when the state must flow through several layers of components, or when the parts that react are provided by different teams. ",[31,1386,1388,1390],{"href":1387},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fhas-vs-container-style-queries\u002F",[1372,1389],{},"() vs Container Style Queries"," compares the approaches in more depth.",[42,1393,1395],{"id":1394},"browser-support","Browser support",[14,1397,1398,1399,1402,1403,1405,1406,1409],{},"Style queries for custom properties are supported in Chrome and Edge 111+, Firefox 151+ and Safari 18+. ",[18,1400,1401],{},"@property"," is supported in Chrome and Edge 85+, Firefox 128+ and Safari 16.4+. ",[18,1404,55],{}," is supported in Chrome and Edge 105+, Firefox 121+ and Safari 15.4+, and ",[18,1407,1408],{},"prefers-reduced-motion"," in Chrome 74+, Edge 79+, Firefox 63+ and Safari 10.1+. In browsers without style queries, the state blocks are ignored and the component stays in its idle appearance; the status text still conveys the state.",[42,1411,1413],{"id":1412},"faq","FAQ",[14,1415,1416,1420,1421,1423,1424,1426],{},[1417,1418,1419],"strong",{},"Can a style query change which animation runs?","\nYes. A style query such as ",[18,1422,148],{}," can set ",[18,1425,1153],{},", duration or any other animation property on descendants. Changing the custom property on the container switches every matching animation inside it.",[14,1428,1429,1432],{},[1417,1430,1431],{},"Why use a style query instead of a class for animation states?","\nA class must be applied to or matched from every element that animates. A custom property set once on a container is inherited, and style queries let each descendant react to it without knowing about classes, which keeps components decoupled.",[14,1434,1435,1438,1439,1442,1443,1446],{},[1417,1436,1437],{},"Does the element need container-type for a style query?","\nNo. Style queries work against the nearest ancestor container, and every element is a style container by default. You only need ",[18,1440,1441],{},"container-type"," for size queries; ",[18,1444,1445],{},"container-name"," helps target a specific ancestor.",[14,1448,1449,1452,1453,1456],{},[1417,1450,1451],{},"What happens in browsers without style queries?","\nThe ",[18,1454,1455],{},"@container style()"," rules are ignored, so descendants keep their base animations. Design the base state as the resting state, and treat the state-specific motion as an enhancement.",[42,1458,1460],{"id":1459},"related","Related",[1462,1463,1464,1470,1477,1484],"ul",{},[1465,1466,1467,1469],"li",{},[31,1468,34],{"href":33}," — the parent guide.",[1465,1471,1472,1476],{},[31,1473,1475],{"href":1474},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-queries-with-custom-properties\u002F","Style Queries With Custom Properties"," — the query syntax in depth.",[1465,1478,1479,1483],{},[31,1480,1482],{"href":1481},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-loading-spinners-and-skeletons\u002F","CSS-Only Loading Spinners and Skeletons"," — the loading motion itself.",[1465,1485,1486,1490],{},[31,1487,1489],{"href":1488},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-fallbacks-and-support\u002F","Style Query Fallbacks and Support"," — handling unsupported browsers.",[293,1492,1493],{},"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 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 .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);}",{"title":177,"searchDepth":201,"depth":201,"links":1495},[1496,1497,1498,1499,1500,1501,1502,1503,1505,1506,1507],{"id":44,"depth":201,"text":45},{"id":151,"depth":201,"text":152},{"id":1170,"depth":201,"text":1171},{"id":1286,"depth":201,"text":1287},{"id":1300,"depth":201,"text":1301},{"id":1336,"depth":201,"text":1337},{"id":1354,"depth":201,"text":1355},{"id":1369,"depth":201,"text":1504},"Style queries versus classes and ()",{"id":1394,"depth":201,"text":1395},{"id":1412,"depth":201,"text":1413},{"id":1459,"depth":201,"text":1460},"Switch a component’s animations from a single custom property with container style queries: loading, success and error motion states set once on the container.","md",{"pageTitle":5,"datePublished":1511,"dateModified":1511,"faq":1512},"2026-09-18",[1513,1515,1517,1519],{"q":1419,"a":1514},"Yes. A style query such as @container style(--state: loading) can set animation-name, duration or any other animation property on descendants. Changing the custom property on the container switches every matching animation inside it.",{"q":1431,"a":1516},"A class must be applied to or matched from every element that animates. A custom property set once on a container is inherited, and style queries let each descendant react to it without knowing about classes, which keeps components decoupled.",{"q":1437,"a":1518},"No. Style queries work against the nearest ancestor container, and every element is a style container by default. You only need container-type for size queries; container-name helps target a specific ancestor.",{"q":1451,"a":1520},"The @container style() rules are ignored, so descendants keep their base animations. Design the base state as the resting state, and treat the state-specific motion as an enhancement.","\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries",{"title":5,"description":1508},"css-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries\u002Findex","CaR6RE953UnzqsDXpk6TtdjWgRmtkR6xeuvBwqpUyVA",[1526,1529,1532,1535,1538,1541,1544,1547,1550,1553,1556,1559,1562,1565,1568,1571,1574,1577,1580,1583,1586,1589,1592,1595,1596,1599,1602,1605,1608,1611,1614,1617,1620,1623,1626,1629,1631,1634,1637,1640,1643,1646,1649,1652,1655,1658,1661,1664,1667,1670,1673,1676,1679,1682,1685,1688,1691,1694,1697,1700,1703,1706,1709,1712,1715,1718,1721,1724,1727,1730,1733,1736,1739,1742,1745,1748,1751,1754,1757,1760,1763,1766,1769,1772,1775,1778,1781,1784,1787,1790,1793,1796,1799,1802,1804,1807,1810,1813,1816,1819,1822,1825,1828,1831,1834,1837,1840,1843,1846,1849,1852,1855,1858,1861,1864,1867,1870,1873,1876,1879,1882,1885,1888,1891,1894,1897,1900,1903,1906,1909,1912,1915,1918,1921,1924,1927,1930,1933,1936,1939,1942,1945,1948,1951,1954,1957,1960,1963,1966,1969,1972,1975,1978,1981,1984,1987,1990,1993,1996,1999,2002,2005,2008,2011,2014,2017,2020,2023,2026,2029,2032,2035,2038,2041,2044,2047,2050,2053,2056,2059,2062,2065,2068,2071,2074,2077,2080],{"path":1527,"title":1528},"\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":1530,"title":1531},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds","Flashing Content and Seizure Thresholds",{"path":1533,"title":1534},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fforced-colors-mode-and-animations","Forced Colors Mode and Animations",{"path":1536,"title":1537},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1539,"title":1540},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fpause-controls-for-looping-animations","Pause Controls for Looping CSS Animations: Meeting WCAG 2.2.2",{"path":1542,"title":1543},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1545,"title":1546},"\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":1548,"title":1549},"\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":1551,"title":1552},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1554,"title":1555},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1557,"title":1558},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fanimated-gradient-borders-with-property","Animated Gradient Borders With @property: A Spinning Highlight Without Extra Elements",{"path":1560,"title":1561},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fclip-path-reveal-animations","Clip-Path Reveal Animations: Wipes, Irises and Corners Without Extra Markup",{"path":1563,"title":1564},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations","Clip-Path & Mask Animations: Animating Visibility Instead of Position",{"path":1566,"title":1567},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fmask-image-fade-edges","Fading Edges With mask-image: Soft Boundaries That Work on Any Background",{"path":1569,"title":1570},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fmorphing-shapes-with-clip-path-polygon","Morphing Shapes With clip-path: polygon(): Point-Matched Transitions",{"path":1572,"title":1573},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fanimating-gradients","Animating CSS Gradients: Smooth Colour Motion Without Jumps",{"path":1575,"title":1576},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fcolor-mix-hover-states","Hover and Active States With color-mix(): One Token, Every Shade",{"path":1578,"title":1579},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions","Color & Theme Transitions: Colour as Part of the Motion System",{"path":1581,"title":1582},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Flight-dark-function-for-themes","Light and Dark Themes With light-dark(): One Declaration per Colour",{"path":1584,"title":1585},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fsmooth-theme-switching-transitions","Smooth Theme Switching: Crossfades, Circular Reveals and No Flash",{"path":1587,"title":1588},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1590,"title":1591},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1593,"title":1594},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Flayout-change-animations-at-container-breakpoints","Animating Changes at Container Breakpoints",{"path":1521,"title":5},{"path":1597,"title":1598},"\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":1600,"title":1601},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":1603,"title":1604},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript","Controlling CSS Animations From JavaScript",{"path":1606,"title":1607},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1609,"title":1610},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui","Interruptible UI: CSS Transitions vs WAAPI",{"path":1612,"title":1613},"\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":1615,"title":1616},"\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":1618,"title":1619},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values","Custom Property Fallbacks and Invalid Values",{"path":1621,"title":1622},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1624,"title":1625},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1627,"title":1628},"\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":1630,"title":1313},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components",{"path":1632,"title":1633},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1635,"title":1636},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1638,"title":1639},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions","Interrupted and Reversing Transitions: What Happens Mid-Flight",{"path":1641,"title":1642},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1644,"title":1645},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-delay-choreography","Choreographing Motion With transition-delay",{"path":1647,"title":1648},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties","The transition Shorthand and Multiple Properties",{"path":1650,"title":1651},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1653,"title":1654},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fanimating-dialog-open-and-close","Animating \u003Cdialog> Open and Close: Both Directions, No Library",{"path":1656,"title":1657},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fbackdrop-animations","Animating ::backdrop: Fades and Blurs Behind Dialogs and Popovers",{"path":1659,"title":1660},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations","Dialog & Popover Animations: Motion for the Top Layer",{"path":1662,"title":1663},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Finterpolate-size-for-height-auto-animation","Animating to height: auto With interpolate-size and calc-size()",{"path":1665,"title":1666},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fpopover-entry-and-exit-transitions","Popover Menus That Animate From Their Anchor",{"path":1668,"title":1669},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations","Choosing Animation Durations: How Long Motion Should Last",{"path":1671,"title":1672},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fcubic-bezier-overshoot-and-anticipation","Overshoot and Anticipation With cubic-bezier(): Motion With Character",{"path":1674,"title":1675},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fentry-vs-exit-easing","Entry vs Exit Easing: Different Curves for Arriving and Leaving",{"path":1677,"title":1678},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design","Easing & Motion Design: Making CSS Motion Feel Intentional",{"path":1680,"title":1681},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Flinear-easing-function-for-springs","Spring and Bounce Easing With linear(): Physical Motion Without JavaScript",{"path":1683,"title":1684},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fsteps-easing-for-sprite-animations","steps() Easing: Sprite Sheets, Typewriters and Other Frame-by-Frame Effects",{"path":1686,"title":1687},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1689,"title":1690},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fbutton-press-and-active-states","Button Press and  States",{"path":1692,"title":1693},"\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":1695,"title":1696},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1698,"title":1699},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fhover-intent-delays-with-transition-delay","Hover Intent Delays With transition-delay: Menus That Don't Flicker",{"path":1701,"title":1702},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1704,"title":1705},"\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":1707,"title":1708},"\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":1710,"title":1711},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1713,"title":1714},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-composition-and-stacking","Stacking Animations With animation-composition",{"path":1716,"title":1717},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-fill-mode-explained","animation-fill-mode: What an Animation Applies Before and After It Runs",{"path":1719,"title":1720},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1722,"title":1723},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1725,"title":1726},"\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":1728,"title":1729},"\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":1731,"title":1732},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1734,"title":1735},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fmulti-step-keyframes-and-per-keyframe-easing","Multi-Step Keyframes and Per-Keyframe Easing",{"path":1737,"title":1738},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1740,"title":1741},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fanimating-box-shadow-and-filters-cheaply","Animating box-shadow and Filters Cheaply",{"path":1743,"title":1744},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcontain-property-for-animation-performance","The contain Property for Animation Performance",{"path":1746,"title":1747},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcss-triggers-layout-paint-composite","Layout, Paint and Composite: What Triggers What",{"path":1749,"title":1750},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1752,"title":1753},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1755,"title":1756},"\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":1758,"title":1759},"\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":1761,"title":1762},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1764,"title":1765},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1767,"title":1768},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-parallax-effects","Scroll-Driven Parallax Effects in CSS",{"path":1770,"title":1771},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1773,"title":1774},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1776,"title":1777},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Ftimeline-scope-for-cross-element-animations","timeline-scope for Cross-Element Animations",{"path":1779,"title":1780},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fview-timeline-and-animation-range","View Timelines and animation-range",{"path":1782,"title":1783},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fcross-document-view-transitions","Cross-Document View Transitions",{"path":1785,"title":1786},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1788,"title":1789},"\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":1791,"title":1792},"\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":1794,"title":1795},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-types-and-classes","View Transition Types and Classes",{"path":1797,"title":1798},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-for-list-reordering","View Transitions for List Reordering",{"path":1800,"title":1801},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":320,"title":1803},"Modern CSS Layouts & Micro-Interactions",{"path":1805,"title":1806},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1808,"title":1809},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1811,"title":1812},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-size-for-matching-widths","anchor-size(): Overlays That Match Their Trigger's Size",{"path":1814,"title":1815},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1817,"title":1818},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1820,"title":1821},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-light-dismiss-and-stacking","Popover Light Dismiss, Nesting and Stacking",{"path":1823,"title":1824},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fposition-area-grid-explained","position-area: The Anchor Placement Grid",{"path":1826,"title":1827},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fcontainer-query-polyfill-tradeoffs","Container Query Polyfills: What They Cost and When to Skip Them",{"path":1829,"title":1830},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1832,"title":1833},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1835,"title":1836},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1838,"title":1839},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fintrinsic-layout-fallbacks-without-queries","Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query",{"path":1841,"title":1842},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ftesting-fallbacks-without-old-browsers","Testing CSS Fallbacks Without an Old Browser",{"path":1844,"title":1845},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-queries-inside-css-nesting","Container Queries Inside CSS Nesting: Keeping Responses Next to the Styles They Change",{"path":1847,"title":1848},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-range-and-logic-operators","Container Query Range Syntax and Logic Operators",{"path":1850,"title":1851},"\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":1853,"title":1854},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1856,"title":1857},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1859,"title":1860},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fdebugging-container-queries-in-devtools","Debugging Container Queries in DevTools: Why a Rule Doesn't Match",{"path":1862,"title":1863},"\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":1865,"title":1866},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1868,"title":1869},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1871,"title":1872},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1874,"title":1875},"\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":1877,"title":1878},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-auto-flow-dense-packing","grid-auto-flow: dense for Packed Layouts",{"path":1880,"title":1881},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-template-areas-responsive-layouts","Responsive Layouts With grid-template-areas: Rearranging Regions by Name",{"path":1883,"title":1884},"\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":1886,"title":1887},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1889,"title":1890},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fmasonry-style-layouts-with-grid","Masonry-Style Layouts With the CSS That Ships Today",{"path":1892,"title":1893},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Foverlapping-elements-with-grid-stacking","Overlapping Elements With Grid Stacking: Layers Without position: absolute",{"path":1895,"title":1896},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1898,"title":1899},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fcentering-in-css-every-method","Centering in CSS: Every Modern Method and When Each One Breaks",{"path":1901,"title":1902},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-basis-vs-width","flex-basis vs width: Which Size a Flex Item Actually Starts From",{"path":1904,"title":1905},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-grow-and-flex-shrink-explained","flex-grow and flex-shrink Explained",{"path":1907,"title":1908},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-wrap-intrinsic-responsive-rows","Breakpoint-Free Responsive Rows With flex-wrap and flex-basis",{"path":1910,"title":1911},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflexbox-gap-and-spacing","Flexbox gap vs Margins: Spacing Items Without Edge Hacks",{"path":1913,"title":1914},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns","Flexbox Layout Patterns: One-Dimensional Layout for Real Components",{"path":1916,"title":1917},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fsticky-footer-with-flexbox-and-grid","Sticky Footer With Flexbox or Grid: Pinning the Footer on Short Pages",{"path":1919,"title":1920},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fclamp-vs-media-query-typography","clamp() Fluid Type vs Media-Query Step Typography: Tradeoffs and Anatomy",{"path":1922,"title":1923},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fdebugging-clamp-values","Debugging clamp(): Values That Are Ignored, Stuck or Never Fluid",{"path":1925,"title":1926},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-line-height-and-measure","Fluid Line Height and Measure: Keeping Text Readable as It Scales",{"path":1928,"title":1929},"\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":1931,"title":1932},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1934,"title":1935},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1937,"title":1938},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1940,"title":1941},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ftext-wrap-balance-and-pretty","text-wrap: balance and pretty: Better Line Breaks Without Manual Breaks",{"path":1943,"title":1944},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1946,"title":1947},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1949,"title":1950},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fcontent-visibility-and-contain-intrinsic-size","content-visibility and contain-intrinsic-size: Rendering Only What Is Near the Screen",{"path":1952,"title":1953},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1955,"title":1956},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Flayout-widths-with-min-max-clamp","Layout Widths With min(), max() and clamp(): Sizing Without Breakpoints",{"path":1958,"title":1959},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1961,"title":1962},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fobject-fit-and-object-position","object-fit and object-position: Images That Fit Any Box",{"path":1964,"title":1965},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1967,"title":1968},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1970,"title":1971},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1973,"title":1974},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcss-scope-for-component-styles","@scope for Component Styles: Short Selectors That Cannot Leak",{"path":1976,"title":1977},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1979,"title":1980},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Frevert-layer-and-revert-keywords","initial, inherit, unset, revert and revert-layer: Undoing Styles Correctly",{"path":1982,"title":1983},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fwriting-a-minimal-modern-reset","Writing a Minimal Modern CSS Reset: Every Line Justified",{"path":1985,"title":1986},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fcontent-aware-card-layouts-with-has","Content-Aware Card Layouts With :has(): One Component, Many Shapes",{"path":1988,"title":1989},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fempty-and-loading-states-with-has","Empty and Loading States With ()",{"path":1991,"title":1992},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fform-validation-layouts-with-has","Form Validation Layouts With :has(): Styling Groups From Field State",{"path":1994,"title":1995},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fhas-selector-performance",":has() Selector Performance: What Is Cheap, What Is Not, and How to Measure",{"path":1997,"title":1998},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fhas-vs-container-style-queries",":has() vs Container Style Queries: Discovered State and Published State",{"path":2000,"title":2001},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has","Parent-Aware Layouts With :has(): Letting Containers React to Their Contents",{"path":2003,"title":2004},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fquantity-queries-with-has","Quantity Queries With :has(): Layouts That Respond to How Many Items There Are",{"path":2006,"title":2007},"\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":2009,"title":2010},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":2012,"title":2013},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":2015,"title":2016},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":2018,"title":2019},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":2021,"title":2022},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-hero-sections-with-container-queries","Responsive Hero Sections With Container Queries",{"path":2024,"title":2025},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":2027,"title":2028},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-pricing-tables","Responsive Pricing Tables: Aligned Features, a Clear Recommendation, Any Width",{"path":2030,"title":2031},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Ftabs-that-become-accordions","Tabs That Become an Accordion: One Component, Two Layouts",{"path":2033,"title":2034},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap","A CSS-Only Carousel With Scroll Snap",{"path":2036,"title":2037},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fhorizontal-scrolling-card-rows","Horizontal Scrolling Card Rows: Swipeable Lists That Stay in Their Lane",{"path":2039,"title":2040},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts","Scroll Snap & Overflow Layouts: Designing Components That Scroll on Purpose",{"path":2042,"title":2043},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Foverscroll-behavior-for-nested-scrolling","overscroll-behavior: Taming Nested Scrolling, Pull-to-Refresh and Back-Swipe",{"path":2045,"title":2046},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fscroll-margin-and-scroll-padding-for-sticky-headers","scroll-margin and scroll-padding: Keeping Targets Clear of Sticky Headers",{"path":2048,"title":2049},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcombining-size-and-style-queries","Combining Size and Style Container Queries",{"path":2051,"title":2052},"\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":2054,"title":2055},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":2057,"title":2058},"\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":2060,"title":2061},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-component-variants","Component Variants With Style Queries: One Token, Many Looks",{"path":2063,"title":2064},"\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",{"path":2066,"title":2067},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fdvh-svh-lvh-mobile-viewport-units","dvh, svh and lvh: Choosing the Right Mobile Viewport Unit",{"path":2069,"title":2070},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Ffull-bleed-sections-in-constrained-layouts","Full-Bleed Sections in a Constrained Layout: Breaking Out Without Breaking the Page",{"path":2072,"title":2073},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout","Viewport Units & Mobile Layout: Designing for the Screen You Actually Get",{"path":2075,"title":2076},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fsafe-area-insets-for-notched-screens","Safe Area Insets: Designing Around Notches, Corners and Home Indicators",{"path":2078,"title":2079},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fviewport-units-vs-container-units","Viewport Units vs Container Units: Choosing the Right Reference Box",{"path":2081,"title":2082},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fvirtual-keyboard-and-interactive-widget","Layouts That Survive the Virtual Keyboard",{"title":2084,"caption":2085,"height":2086,"html":2087,"css":2088},"Motion states chosen by a style query","Pick a state. The radios set --state on the container through :has(); the icon's animation is chosen by @container style() queries. Browsers without style queries keep the idle look.",200,"\n\u003Cdiv class=\"demo\">\n  \u003Cfieldset class=\"states\">\n    \u003Clegend>State\u003C\u002Flegend>\n    \u003Clabel>\u003Cinput type=\"radio\" name=\"s\" value=\"idle\" checked> idle\u003C\u002Flabel>\n    \u003Clabel>\u003Cinput type=\"radio\" name=\"s\" value=\"loading\"> loading\u003C\u002Flabel>\n    \u003Clabel>\u003Cinput type=\"radio\" name=\"s\" value=\"success\"> success\u003C\u002Flabel>\n    \u003Clabel>\u003Cinput type=\"radio\" name=\"s\" value=\"error\"> error\u003C\u002Flabel>\n  \u003C\u002Ffieldset>\n  \u003Cdiv class=\"upload\">\n    \u003Cspan class=\"upload__icon\" aria-hidden=\"true\">\u003C\u002Fspan>\n    \u003Cspan class=\"upload__label\">report.pdf\u003C\u002Fspan>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>","\n.demo { display: grid; gap: 1rem; padding: 1rem; }\n.states { display: flex; flex-wrap: wrap; gap: 0.75rem; border: 1px solid var(--demo-border); border-radius: 8px; padding: 0.5rem 0.75rem; }\n.states legend { font-size: 0.8rem; color: var(--demo-muted); padding-inline: 0.25rem; }\n.upload { container-name: upload; --state: idle; display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1rem; border: 1px solid var(--demo-border); border-radius: 10px; inline-size: fit-content; background: var(--demo-surface); }\n.demo:has([value=\"loading\"]:checked) .upload { --state: loading; }\n.demo:has([value=\"success\"]:checked) .upload { --state: success; }\n.demo:has([value=\"error\"]:checked) .upload { --state: error; }\n.upload__icon { inline-size: 1.25rem; aspect-ratio: 1; border-radius: 50%; border: 3px solid #94a3b8; }\n@container upload style(--state: loading) { .upload__icon { border-color: #2563eb #2563eb transparent transparent; animation: spin 800ms linear infinite; } }\n@container upload style(--state: success) { .upload__icon { border-color: #16a34a; background: #16a34a; animation: pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1); } }\n@container upload style(--state: error) { .upload__icon { border-color: #dc2626; animation: shake 360ms ease-in-out; } }\n@keyframes spin { to { rotate: 1turn; } }\n@keyframes pop { from { scale: 0.6; } }\n@keyframes shake { 25% { translate: -4px 0; } 50% { translate: 4px 0; } 75% { translate: -2px 0; } }\n@media (prefers-reduced-motion: reduce) { .upload__icon { animation-duration: 1ms !important; animation-iteration-count: 1 !important; } }",1789717749391]