[{"data":1,"prerenderedAt":1770},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values":3,"content-all-pages":1205,"live-demo:var-fallback-cases":1764},{"id":4,"title":5,"body":6,"description":1188,"extension":1189,"meta":1190,"navigation":422,"path":1201,"seo":1202,"stem":1203,"__hash__":1204},"content\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values\u002Findex.md","Custom Property Fallbacks and Invalid Values",{"type":7,"value":8,"toc":1176},"minimark",[9,13,41,46,61,162,166,196,200,203,207,812,821,825,828,886,952,956,959,1029,1032,1036,1046,1063,1067,1080,1084,1100,1104,1113,1122,1134,1143,1147,1173],[10,11,5],"h1",{"id":12},"custom-property-fallbacks-and-invalid-values",[14,15,16,17,21,22,25,26,29,30,35,36,40],"p",{},"Custom properties are the backbone of themable components and token-driven motion, and the second argument of ",[18,19,20],"code",{},"var()"," — the fallback — looks like a safety net. It is a narrower net than most people assume. The fallback covers a missing property, not a wrong one: set ",[18,23,24],{},"--duration: fast"," by mistake and ",[18,27,28],{},"transition-duration: var(--duration, 200ms)"," does not use 200ms. It becomes invalid, and the property quietly reverts to its initial value, discarding every earlier declaration that would have worked. Understanding when fallbacks apply, what \"invalid at computed-value time\" means, and how registered properties change the picture prevents a whole category of mysteriously missing animations. This page belongs to ",[31,32,34],"a",{"href":33},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002F","CSS Custom Properties Architecture"," 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},"when-the-fallback-applies","When the fallback applies",[14,47,48,49,52,53,56,57,60],{},"The fallback in ",[18,50,51],{},"var(--name, fallback)"," is used only when ",[18,54,55],{},"--name"," has no value — it was never declared on the element or its ancestors (for an inheriting property), or it was set to the ",[18,58,59],{},"initial"," keyword, which gives a custom property its \"guaranteed-invalid\" initial value. In every other case, the property's value is substituted, whether or not it makes sense where it lands.",[62,63,69,70,69,74,69,78,69,86,69,96,69,101,69,108,69,113,69,117,69,121,69,126,69,131,69,136,69,141,69,146,69,152,69,156,69,159],"svg",{"viewBox":64,"role":65,"ariaLabel":66,"xmlns":67,"style":68},"0 0 720 300","img","Decision flow for var(): if the custom property is unset, the fallback is used; if it has a value, the value is substituted; if the result is invalid for the property, the property becomes unset","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[71,72,73],"title",{},"Three outcomes for a var() reference",[75,76,77],"desc",{},"A flow diagram. Is the custom property set? If no, the fallback is used. If yes, its value is substituted. Then: is the result valid for the property? If yes, it applies. If no, the declaration is invalid at computed-value time and the property behaves as unset, inheriting or taking its initial value; earlier declarations are not revived.",[79,80,85],"text",{"textAnchor":81,"x":82,"y":83,"style":84},"middle","360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","The fallback covers \"missing\", not \"wrong\"",[87,88],"rect",{"x":89,"y":90,"width":89,"height":91,"rx":92,"fill":93,"stroke":94,"strokeWidth":95},"240","48","44","8","none","currentColor","1.5",[79,97,100],{"textAnchor":81,"x":82,"y":98,"style":99},"75","text-anchor:middle;fill:currentColor;font:13px sans-serif","Is --duration set?",[87,102],{"x":103,"y":104,"width":105,"height":91,"rx":92,"fill":106,"opacity":107},"40","130","200","#7aa2ff","0.3",[79,109,112],{"textAnchor":81,"x":110,"y":111,"style":99},"140","157","no: use fallback",[87,114],{"x":115,"y":104,"width":116,"height":91,"rx":92,"fill":93,"stroke":94,"strokeWidth":95},"400","280",[79,118,120],{"textAnchor":81,"x":119,"y":111,"style":99},"540","yes: substitute, then valid?",[87,122],{"x":123,"y":124,"width":125,"height":91,"rx":92,"fill":106,"opacity":107},"300","220","170",[79,127,130],{"textAnchor":81,"x":128,"y":129,"style":99},"385","247","valid: applies",[87,132],{"x":133,"y":124,"width":134,"height":91,"rx":92,"fill":94,"opacity":135},"500","190","0.15",[79,137,140],{"textAnchor":81,"x":138,"y":89,"style":139},"595","text-anchor:middle;fill:currentColor;font:12px sans-serif","invalid: acts as unset",[79,142,145],{"textAnchor":81,"x":138,"y":143,"style":144},"256","text-anchor:middle;fill:currentColor;font:11px sans-serif","earlier rules not revived",[147,148],"line",{"x1":123,"y1":149,"x2":150,"y2":104,"stroke":94,"strokeWidth":95,"opacity":151},"92","160","0.6",[147,153],{"x1":154,"y1":149,"x2":155,"y2":104,"stroke":94,"strokeWidth":95,"opacity":151},"420","530",[147,157],{"x1":133,"y1":158,"x2":115,"y2":124,"stroke":94,"strokeWidth":95,"opacity":151},"174",[147,160],{"x1":161,"y1":158,"x2":138,"y2":124,"stroke":94,"strokeWidth":95,"opacity":151},"580",[42,163,165],{"id":164},"invalid-at-computed-value-time","Invalid at computed-value time",[14,167,168,169,172,173,175,176,179,180,183,184,187,188,191,192,195],{},"A normal invalid declaration, such as ",[18,170,171],{},"transition-duration: fast;",", is thrown away at parse time. The cascade never sees it, so an earlier valid declaration wins. A declaration that contains ",[18,174,20],{}," cannot be checked at parse time, because the browser does not yet know what will be substituted. It is assumed valid, it wins the cascade, and only later — at computed-value time — does the browser discover that ",[18,177,178],{},"fast"," is not a time. At that point there is no going back to the losing declarations. The specification's answer is to treat the property as ",[18,181,182],{},"unset",": inherited properties such as ",[18,185,186],{},"color"," inherit from the parent, and non-inherited ones such as ",[18,189,190],{},"transition-duration"," take their initial value, ",[18,193,194],{},"0s",".",[42,197,199],{"id":198},"the-complete-implementation","The complete implementation",[14,201,202],{},"The demo shows three buttons. The first gets a valid duration token, the second has no token and uses the fallback, and the third has a typo'd token that silently kills its transition. Hover each to compare.",[204,205],"live-demo",{"name":206},"var-fallback-cases",[208,209,214],"pre",{"className":210,"code":211,"language":212,"meta":213,"style":213},"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>var() fallbacks and invalid values\u003C\u002Ftitle>\n\u003Cstyle>\n  body { font: 15px\u002F1.5 system-ui, sans-serif; margin: 2rem; display: flex; gap: 1rem; flex-wrap: wrap; }\n\n  .btn {\n    padding: 0.75rem 1.25rem;\n    border: 0;\n    border-radius: 8px;\n    background: #2563eb;\n    color: #fff;\n    font: inherit;\n    \u002F* An earlier, valid declaration ... *\u002F\n    transition: background-color 400ms ease-out, translate 400ms ease-out;\n    \u002F* ... is overridden by this one, whatever --motion-duration turns out to be. *\u002F\n    transition-duration: var(--motion-duration, 600ms);\n  }\n  .btn:hover { background: #7c3aed; translate: 0 -4px; }\n\n  .btn--token   { --motion-duration: 250ms; }   \u002F* valid: 250ms *\u002F\n  \u002F* .btn--missing sets nothing: the fallback 600ms applies *\u002F\n  .btn--typo    { --motion-duration: fast; }    \u002F* invalid at computed-value time: 0s *\u002F\n\u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Cbutton class=\"btn btn--token\" type=\"button\">Token: 250ms\u003C\u002Fbutton>\n  \u003Cbutton class=\"btn btn--missing\" type=\"button\">Missing: fallback\u003C\u002Fbutton>\n  \u003Cbutton class=\"btn btn--typo\" type=\"button\">Typo: no transition\u003C\u002Fbutton>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html","",[18,215,216,235,255,265,283,308,322,332,417,424,433,454,467,481,494,507,520,527,555,561,589,595,627,632,656,662,679,689,698,708,740,767,794,803],{"__ignoreMap":213},[217,218,220,224,228,232],"span",{"class":147,"line":219},1,[217,221,223],{"class":222},"suds8","\u003C!",[217,225,227],{"class":226},"sne4z","doctype",[217,229,231],{"class":230},"s-5SL"," html",[217,233,234],{"class":222},">\n",[217,236,238,241,243,246,249,253],{"class":147,"line":237},2,[217,239,240],{"class":222},"\u003C",[217,242,212],{"class":226},[217,244,245],{"class":230}," lang",[217,247,248],{"class":222},"=",[217,250,252],{"class":251},"sT6z2","\"en\"",[217,254,234],{"class":222},[217,256,258,260,263],{"class":147,"line":257},3,[217,259,240],{"class":222},[217,261,262],{"class":226},"head",[217,264,234],{"class":222},[217,266,268,270,273,276,278,281],{"class":147,"line":267},4,[217,269,240],{"class":222},[217,271,272],{"class":226},"meta",[217,274,275],{"class":230}," charset",[217,277,248],{"class":222},[217,279,280],{"class":251},"\"utf-8\"",[217,282,234],{"class":222},[217,284,286,288,290,293,295,298,301,303,306],{"class":147,"line":285},5,[217,287,240],{"class":222},[217,289,272],{"class":226},[217,291,292],{"class":230}," name",[217,294,248],{"class":222},[217,296,297],{"class":251},"\"viewport\"",[217,299,300],{"class":230}," content",[217,302,248],{"class":222},[217,304,305],{"class":251},"\"width=device-width, initial-scale=1\"",[217,307,234],{"class":222},[217,309,311,313,315,318,320],{"class":147,"line":310},6,[217,312,240],{"class":222},[217,314,71],{"class":226},[217,316,317],{"class":222},">var() fallbacks and invalid values\u003C\u002F",[217,319,71],{"class":226},[217,321,234],{"class":222},[217,323,325,327,330],{"class":147,"line":324},7,[217,326,240],{"class":222},[217,328,329],{"class":226},"style",[217,331,234],{"class":222},[217,333,335,338,341,344,347,350,354,357,359,362,365,368,371,374,376,379,382,384,387,389,392,394,397,399,402,404,406,409,411,414],{"class":147,"line":334},8,[217,336,337],{"class":226},"  body",[217,339,340],{"class":222}," { ",[217,342,343],{"class":230},"font",[217,345,346],{"class":222},": ",[217,348,349],{"class":230},"15",[217,351,353],{"class":352},"sHUrx","px",[217,355,356],{"class":222},"\u002F",[217,358,95],{"class":230},[217,360,361],{"class":230}," system-ui",[217,363,364],{"class":222},", ",[217,366,367],{"class":230},"sans-serif",[217,369,370],{"class":222},"; ",[217,372,373],{"class":230},"margin",[217,375,346],{"class":222},[217,377,378],{"class":230},"2",[217,380,381],{"class":352},"rem",[217,383,370],{"class":222},[217,385,386],{"class":230},"display",[217,388,346],{"class":222},[217,390,391],{"class":230},"flex",[217,393,370],{"class":222},[217,395,396],{"class":230},"gap",[217,398,346],{"class":222},[217,400,401],{"class":230},"1",[217,403,381],{"class":352},[217,405,370],{"class":222},[217,407,408],{"class":230},"flex-wrap",[217,410,346],{"class":222},[217,412,413],{"class":230},"wrap",[217,415,416],{"class":222},"; }\n",[217,418,420],{"class":147,"line":419},9,[217,421,423],{"emptyLinePlaceholder":422},true,"\n",[217,425,427,430],{"class":147,"line":426},10,[217,428,429],{"class":230},"  .btn",[217,431,432],{"class":222}," {\n",[217,434,436,439,441,444,446,449,451],{"class":147,"line":435},11,[217,437,438],{"class":230},"    padding",[217,440,346],{"class":222},[217,442,443],{"class":230},"0.75",[217,445,381],{"class":352},[217,447,448],{"class":230}," 1.25",[217,450,381],{"class":352},[217,452,453],{"class":222},";\n",[217,455,457,460,462,465],{"class":147,"line":456},12,[217,458,459],{"class":230},"    border",[217,461,346],{"class":222},[217,463,464],{"class":230},"0",[217,466,453],{"class":222},[217,468,470,473,475,477,479],{"class":147,"line":469},13,[217,471,472],{"class":230},"    border-radius",[217,474,346],{"class":222},[217,476,92],{"class":230},[217,478,353],{"class":352},[217,480,453],{"class":222},[217,482,484,487,489,492],{"class":147,"line":483},14,[217,485,486],{"class":230},"    background",[217,488,346],{"class":222},[217,490,491],{"class":230},"#2563eb",[217,493,453],{"class":222},[217,495,497,500,502,505],{"class":147,"line":496},15,[217,498,499],{"class":230},"    color",[217,501,346],{"class":222},[217,503,504],{"class":230},"#fff",[217,506,453],{"class":222},[217,508,510,513,515,518],{"class":147,"line":509},16,[217,511,512],{"class":230},"    font",[217,514,346],{"class":222},[217,516,517],{"class":230},"inherit",[217,519,453],{"class":222},[217,521,523],{"class":147,"line":522},17,[217,524,526],{"class":525},"sLBg1","    \u002F* An earlier, valid declaration ... *\u002F\n",[217,528,530,533,536,538,541,544,547,549,551,553],{"class":147,"line":529},18,[217,531,532],{"class":230},"    transition",[217,534,535],{"class":222},": background-color ",[217,537,115],{"class":230},[217,539,540],{"class":352},"ms",[217,542,543],{"class":230}," ease-out",[217,545,546],{"class":222},", translate ",[217,548,115],{"class":230},[217,550,540],{"class":352},[217,552,543],{"class":230},[217,554,453],{"class":222},[217,556,558],{"class":147,"line":557},19,[217,559,560],{"class":525},"    \u002F* ... is overridden by this one, whatever --motion-duration turns out to be. *\u002F\n",[217,562,564,567,569,572,575,579,581,584,586],{"class":147,"line":563},20,[217,565,566],{"class":230},"    transition-duration",[217,568,346],{"class":222},[217,570,571],{"class":230},"var",[217,573,574],{"class":222},"(",[217,576,578],{"class":577},"soyes","--motion-duration",[217,580,364],{"class":222},[217,582,583],{"class":230},"600",[217,585,540],{"class":352},[217,587,588],{"class":222},");\n",[217,590,592],{"class":147,"line":591},21,[217,593,594],{"class":222},"  }\n",[217,596,598,601,603,606,608,611,613,616,618,620,623,625],{"class":147,"line":597},22,[217,599,600],{"class":230},"  .btn:hover",[217,602,340],{"class":222},[217,604,605],{"class":230},"background",[217,607,346],{"class":222},[217,609,610],{"class":230},"#7c3aed",[217,612,370],{"class":222},[217,614,615],{"class":230},"translate",[217,617,346],{"class":222},[217,619,464],{"class":230},[217,621,622],{"class":230}," -4",[217,624,353],{"class":352},[217,626,416],{"class":222},[217,628,630],{"class":147,"line":629},23,[217,631,423],{"emptyLinePlaceholder":422},[217,633,635,638,641,643,645,648,650,653],{"class":147,"line":634},24,[217,636,637],{"class":230},"  .btn--token",[217,639,640],{"class":222},"   { ",[217,642,578],{"class":577},[217,644,346],{"class":222},[217,646,647],{"class":230},"250",[217,649,540],{"class":352},[217,651,652],{"class":222},"; }   ",[217,654,655],{"class":525},"\u002F* valid: 250ms *\u002F\n",[217,657,659],{"class":147,"line":658},25,[217,660,661],{"class":525},"  \u002F* .btn--missing sets nothing: the fallback 600ms applies *\u002F\n",[217,663,665,668,671,673,676],{"class":147,"line":664},26,[217,666,667],{"class":230},"  .btn--typo",[217,669,670],{"class":222},"    { ",[217,672,578],{"class":577},[217,674,675],{"class":222},": fast; }    ",[217,677,678],{"class":525},"\u002F* invalid at computed-value time: 0s *\u002F\n",[217,680,682,685,687],{"class":147,"line":681},27,[217,683,684],{"class":222},"\u003C\u002F",[217,686,329],{"class":226},[217,688,234],{"class":222},[217,690,692,694,696],{"class":147,"line":691},28,[217,693,684],{"class":222},[217,695,262],{"class":226},[217,697,234],{"class":222},[217,699,701,703,706],{"class":147,"line":700},29,[217,702,240],{"class":222},[217,704,705],{"class":226},"body",[217,707,234],{"class":222},[217,709,711,714,717,720,722,725,728,730,733,736,738],{"class":147,"line":710},30,[217,712,713],{"class":222},"  \u003C",[217,715,716],{"class":226},"button",[217,718,719],{"class":230}," class",[217,721,248],{"class":222},[217,723,724],{"class":251},"\"btn btn--token\"",[217,726,727],{"class":230}," type",[217,729,248],{"class":222},[217,731,732],{"class":251},"\"button\"",[217,734,735],{"class":222},">Token: 250ms\u003C\u002F",[217,737,716],{"class":226},[217,739,234],{"class":222},[217,741,743,745,747,749,751,754,756,758,760,763,765],{"class":147,"line":742},31,[217,744,713],{"class":222},[217,746,716],{"class":226},[217,748,719],{"class":230},[217,750,248],{"class":222},[217,752,753],{"class":251},"\"btn btn--missing\"",[217,755,727],{"class":230},[217,757,248],{"class":222},[217,759,732],{"class":251},[217,761,762],{"class":222},">Missing: fallback\u003C\u002F",[217,764,716],{"class":226},[217,766,234],{"class":222},[217,768,770,772,774,776,778,781,783,785,787,790,792],{"class":147,"line":769},32,[217,771,713],{"class":222},[217,773,716],{"class":226},[217,775,719],{"class":230},[217,777,248],{"class":222},[217,779,780],{"class":251},"\"btn btn--typo\"",[217,782,727],{"class":230},[217,784,248],{"class":222},[217,786,732],{"class":251},[217,788,789],{"class":222},">Typo: no transition\u003C\u002F",[217,791,716],{"class":226},[217,793,234],{"class":222},[217,795,797,799,801],{"class":147,"line":796},33,[217,798,684],{"class":222},[217,800,705],{"class":226},[217,802,234],{"class":222},[217,804,806,808,810],{"class":147,"line":805},34,[217,807,684],{"class":222},[217,809,212],{"class":226},[217,811,234],{"class":222},[14,813,814,815,817,818,820],{},"The third button is the trap. Its author probably expected either the fallback (600ms) or the shorthand's 400ms. It gets neither: the ",[18,816,190],{}," declaration wins the cascade, becomes invalid after substitution, and resets to ",[18,819,194],{},". The button changes colour instantly and there is no error anywhere.",[42,822,824],{"id":823},"the-key-technique-validate-at-the-boundary","The key technique: validate at the boundary",[14,826,827],{},"Because fallbacks do not protect against wrong values, protection has to come from elsewhere. Three approaches work, from strongest to lightest:",[829,830,831,866,876],"ol",{},[832,833,834,838,839,842,843,846,847,850,851,853,854,857,858,860,861,865],"li",{},[835,836,837],"strong",{},"Register the property."," ",[18,840,841],{},"@property --motion-duration { syntax: \"\u003Ctime>\"; inherits: true; initial-value: 200ms; }"," makes the browser check every value against the ",[18,844,845],{},"\u003Ctime>"," syntax. ",[18,848,849],{},"--motion-duration: fast"," no longer produces a broken ",[18,852,190],{},"; instead the custom property itself is treated as unset, so it inherits its parent's valid duration or takes the registered ",[18,855,856],{},"initial-value"," of 200ms. The typo still needs fixing, but the damage is contained to one sensible default instead of a silent ",[18,859,194],{},". ",[31,862,864],{"href":863},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fregistered-properties-and-type-safety\u002F","Registered Properties and Type Safety"," covers syntax strings in depth.",[832,867,868,871,872,875],{},[835,869,870],{},"Keep tokens in one place."," If every duration token is defined in a single ",[18,873,874],{},":root"," block with valid values, and components only ever reference tokens rather than set them, typos have one place to hide.",[832,877,878,881,882,885],{},[835,879,880],{},"Use the fallback for its real job."," Fallbacks are ideal for optional component APIs: ",[18,883,884],{},"padding: var(--card-padding, 1rem)"," lets a parent customise the padding but works without it. They are the right tool for \"may be missing\" and the wrong one for \"may be wrong\".",[62,887,69,890,69,893,69,896,69,899,69,906,69,910,69,916,69,920,69,924,69,928,69,932,69,937,69,939,69,942,69,945,69,948],{"viewBox":888,"role":65,"ariaLabel":889,"xmlns":67,"style":68},"0 0 720 260","Comparison of an unregistered and a registered custom property receiving the invalid value fast: unregistered, the transition-duration becomes 0s; registered, the custom property falls back to its initial value 200ms",[71,891,892],{},"Registration guarantees a value of the right type",[75,894,895],{},"Left panel, unregistered: --motion-duration fast is accepted, substituted into transition-duration, found invalid, and the property resets to 0 seconds. Right panel, registered with syntax time and initial-value 200ms: fast fails the syntax check, so the custom property falls back to its inherited value or 200ms and transition-duration is 200ms.",[79,897,898],{"textAnchor":81,"x":82,"y":83,"style":84},"Same typo, different outcome",[87,900],{"x":901,"y":902,"width":903,"height":125,"rx":904,"fill":94,"opacity":905},"30","50","315","10","0.08",[87,907],{"x":908,"y":902,"width":903,"height":125,"rx":904,"fill":106,"opacity":909},"375","0.2",[79,911,915],{"textAnchor":81,"x":912,"y":913,"style":914},"187","78","text-anchor:middle;fill:currentColor;font:600 13px sans-serif","unregistered",[79,917,919],{"textAnchor":81,"x":918,"y":913,"style":914},"532","registered as \u003Ctime>",[79,921,849],{"textAnchor":81,"x":912,"y":922,"style":923},"112","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace",[79,925,927],{"textAnchor":81,"x":912,"y":926,"style":139},"138","accepted as a token string",[79,929,931],{"textAnchor":81,"x":912,"y":930,"style":139},"164","substituted, then invalid",[79,933,936],{"textAnchor":81,"x":912,"y":934,"style":935},"196","text-anchor:middle;fill:currentColor;font:600 12px ui-monospace,monospace","duration: 0s",[79,938,849],{"textAnchor":81,"x":918,"y":922,"style":923},[79,940,941],{"textAnchor":81,"x":918,"y":926,"style":139},"fails the \u003Ctime> check",[79,943,944],{"textAnchor":81,"x":918,"y":930,"style":139},"inherited or initial-value",[79,946,947],{"textAnchor":81,"x":918,"y":934,"style":935},"duration: 200ms",[79,949,951],{"textAnchor":81,"x":82,"y":950,"style":139},"246","A registered property can never hold a value that fails its syntax.",[42,953,955],{"id":954},"where-this-bites-animations-hardest","Where this bites animations hardest",[14,957,958],{},"Motion code is unusually exposed to invalid substitution because so much of it is assembled from tokens. A few patterns come up repeatedly:",[960,961,962,986,1003,1020],"ul",{},[832,963,964,838,967,970,971,974,975,978,979,982,983,195],{},[835,965,966],{},"Unitless numbers in times.",[18,968,969],{},"--stagger: 80"," multiplied into ",[18,972,973],{},"transition-delay: calc(var(--i) * var(--stagger))"," produces a number, not a time, so the delay is invalid and every item animates at once. Store the token with its unit, ",[18,976,977],{},"80ms",", or multiply by ",[18,980,981],{},"1ms"," inside the ",[18,984,985],{},"calc()",[832,987,988,991,992,995,996,999,1000,1002],{},[835,989,990],{},"Keywords where values are expected."," Design tokens exported from tools sometimes carry names such as ",[18,993,994],{},"slow"," or ",[18,997,998],{},"standard"," rather than the values those names stand for. Each one produces a silent ",[18,1001,194],{}," or a default easing.",[832,1004,1005,838,1008,1011,1012,1015,1016,1019],{},[835,1006,1007],{},"Whole shorthands in one token.",[18,1009,1010],{},"--enter: 300ms ease-out"," works inside ",[18,1013,1014],{},"transition: opacity var(--enter)"," but not inside ",[18,1017,1018],{},"transition-duration: var(--enter)",", which cannot accept an easing. Keep duration and easing tokens separate so each fits every property that uses it.",[832,1021,1022,838,1025,1028],{},[835,1023,1024],{},"Empty values.",[18,1026,1027],{},"--delay: ;"," is a valid, empty custom property value, not a missing one, so the fallback is skipped and the referencing declaration becomes invalid.",[14,1030,1031],{},"In each case the element still renders, which is why these bugs survive review. A quick check in the Computed pane, or a registered property for each motion token, catches them early.",[42,1033,1035],{"id":1034},"nested-fallbacks-and-fallback-lists","Nested fallbacks and fallback lists",[14,1037,1038,1039,1041,1042,1045],{},"A fallback can itself contain ",[18,1040,20],{},", which builds a chain: ",[18,1043,1044],{},"var(--button-duration, var(--motion-duration, 200ms))",". The browser tries the component-level token, then the global token, then the literal. This is a clean way to let components override a site-wide value. Keep chains to two levels; deeper nesting becomes hard to reason about and hard to debug in DevTools, which shows only the final computed value.",[14,1047,1048,1049,1052,1053,364,1056,1059,1060,195],{},"Everything after the first comma is the fallback, commas included. ",[18,1050,1051],{},"var(--shadow, 0 1px 2px black, 0 4px 8px black)"," has a fallback of two shadows, which is convenient for list-valued properties like ",[18,1054,1055],{},"box-shadow",[18,1057,1058],{},"transition"," and ",[18,1061,1062],{},"font-family",[42,1064,1066],{"id":1065},"debugging-invalid-substitutions","Debugging invalid substitutions",[14,1068,1069,1070,1073,1074,1076,1077,1079],{},"DevTools makes invalid-at-computed-value-time declarations visible if you know where to look. In the Styles pane, the declaration appears normal — not struck through — because it was valid at parse time. Switch to the Computed pane and the property shows its initial value, with the winning declaration listed as its source. That mismatch, \"the rule that wins says ",[18,1071,1072],{},"var(--x, 600ms)"," but the computed value is ",[18,1075,194],{},"\", is the signature of the problem. Once you have seen it a couple of times, it becomes the first thing to check whenever a token-driven animation stops working. Hovering the ",[18,1078,20],{}," reference in Chromium shows the substituted value, which usually reveals the typo immediately.",[42,1081,1083],{"id":1082},"browser-support","Browser support",[14,1085,1086,1087,1089,1090,1093,1094,1096,1097,1099],{},"Custom properties and ",[18,1088,20],{}," fallbacks are supported in every current browser. ",[18,1091,1092],{},"@property"," is supported in Chrome and Edge 85+, Firefox 128+ and Safari 16.4+; browsers without it treat the property as unregistered, which returns to the default behaviour described above. The ",[18,1095,1058],{}," shorthand is supported in Chrome 26+, Edge 12+, Firefox 16+ and Safari 9+, and the standalone ",[18,1098,615],{}," property in Chrome and Edge 104+, Firefox 72+ and Safari 14.1+.",[42,1101,1103],{"id":1102},"faq","FAQ",[14,1105,1106,1109,1110,1112],{},[835,1107,1108],{},"When is the fallback in var() used?","\nOnly when the custom property is not set, or is set to the initial guaranteed-invalid value, for example with the ",[18,1111,59],{}," keyword. If the property holds any value, even one that makes no sense for the property using it, the fallback is ignored.",[14,1114,1115,1118,1119,1121],{},[835,1116,1117],{},"What does invalid at computed-value time mean?","\nThe declaration looked valid when the stylesheet was parsed because it contained ",[18,1120,20],{},", but after substitution the value is invalid for the property. The browser cannot go back to an earlier declaration, so the property behaves as unset: inherited properties inherit and others take their initial value.",[14,1123,1124,1127,1128,1130,1131,1133],{},[835,1125,1126],{},"Why does a bad custom property value not fall back to my earlier declaration?","\nThe cascade has already chosen the declaration containing ",[18,1129,20],{}," before substitution happens. When that value turns out invalid, the earlier declaration is no longer in play. Register the property with ",[18,1132,1092],{}," and an initial value, or keep tokens validated in one place, to guard against it.",[14,1135,1136,1139,1140,1142],{},[835,1137,1138],{},"How does @property change fallback behaviour?","\nA registered property checks values against its syntax. A value that does not match makes the custom property itself fall back to its inherited value or its registered ",[18,1141,856],{},", so anything referencing it always receives a value of the right type. That makes it much more predictable.",[42,1144,1146],{"id":1145},"related","Related",[960,1148,1149,1154,1159,1166],{},[832,1150,1151,1153],{},[31,1152,34],{"href":33}," — the parent guide.",[832,1155,1156,1158],{},[31,1157,864],{"href":863}," — syntax strings and initial values.",[832,1160,1161,1165],{},[31,1162,1164],{"href":1163},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations\u002F","Fluid Spacing Tokens Driving Transition Durations"," — tokens that must stay valid.",[832,1167,1168,1172],{},[31,1169,1171],{"href":1170},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties\u002F","Transition Shorthand and Multiple Properties"," — how longhands override the shorthand.",[329,1174,1175],{},"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 .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}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":213,"searchDepth":237,"depth":237,"links":1177},[1178,1179,1180,1181,1182,1183,1184,1185,1186,1187],{"id":44,"depth":237,"text":45},{"id":164,"depth":237,"text":165},{"id":198,"depth":237,"text":199},{"id":823,"depth":237,"text":824},{"id":954,"depth":237,"text":955},{"id":1034,"depth":237,"text":1035},{"id":1065,"depth":237,"text":1066},{"id":1082,"depth":237,"text":1083},{"id":1102,"depth":237,"text":1103},{"id":1145,"depth":237,"text":1146},"When var() fallbacks apply and when they do not: invalid at computed-value time, why earlier declarations are lost, nested fallbacks, and registered properties.","md",{"pageTitle":5,"datePublished":1191,"dateModified":1191,"faq":1192},"2026-09-18",[1193,1195,1197,1199],{"q":1108,"a":1194},"Only when the custom property is not set, or is set to the initial guaranteed-invalid value, for example with the initial keyword. If the property holds any value, even one that makes no sense for the property using it, the fallback is ignored.",{"q":1117,"a":1196},"The declaration looked valid when the stylesheet was parsed because it contained var(), but after substitution the value is invalid for the property. The browser cannot go back to an earlier declaration, so the property behaves as unset: inherited properties inherit and others take their initial value.",{"q":1126,"a":1198},"The cascade has already chosen the declaration containing var() before substitution happens. When that value turns out invalid, the earlier declaration is no longer in play. Register the property with @property and an initial value, or keep tokens validated in one place, to guard against it.",{"q":1138,"a":1200},"A registered property checks values against its syntax. A value that does not match makes the custom property itself fall back to its inherited value or its registered initial-value, so anything referencing it always receives a value of the right type. That makes it much more predictable.","\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values",{"title":5,"description":1188},"css-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values\u002Findex","psz-03kF9qTsdxRacOsA1t9msl534VZBjPDzSZD9NtQ",[1206,1209,1212,1215,1218,1221,1224,1227,1230,1233,1236,1239,1242,1245,1248,1251,1254,1257,1260,1263,1266,1269,1272,1275,1278,1281,1284,1287,1290,1293,1296,1299,1300,1303,1306,1309,1312,1315,1318,1321,1324,1327,1330,1333,1336,1339,1342,1345,1348,1351,1354,1357,1360,1363,1366,1369,1372,1375,1378,1381,1384,1387,1390,1393,1396,1399,1402,1405,1408,1411,1414,1417,1420,1423,1426,1429,1432,1435,1438,1441,1444,1447,1450,1453,1456,1459,1462,1465,1468,1471,1474,1477,1480,1483,1485,1488,1491,1494,1497,1500,1503,1506,1509,1512,1515,1518,1521,1524,1527,1530,1533,1536,1539,1542,1545,1548,1551,1554,1557,1560,1563,1566,1569,1572,1575,1578,1581,1584,1587,1590,1593,1596,1599,1602,1605,1608,1611,1614,1617,1620,1623,1626,1629,1632,1635,1638,1641,1644,1647,1650,1653,1656,1659,1662,1665,1668,1671,1674,1677,1680,1683,1686,1689,1692,1695,1698,1701,1704,1707,1710,1713,1716,1719,1722,1725,1728,1731,1734,1737,1740,1743,1746,1749,1752,1755,1758,1761],{"path":1207,"title":1208},"\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":1210,"title":1211},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds","Flashing Content and Seizure Thresholds",{"path":1213,"title":1214},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fforced-colors-mode-and-animations","Forced Colors Mode and Animations",{"path":1216,"title":1217},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1219,"title":1220},"\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":1222,"title":1223},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1225,"title":1226},"\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":1228,"title":1229},"\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":1231,"title":1232},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1234,"title":1235},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1237,"title":1238},"\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":1240,"title":1241},"\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":1243,"title":1244},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations","Clip-Path & Mask Animations: Animating Visibility Instead of Position",{"path":1246,"title":1247},"\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":1249,"title":1250},"\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":1252,"title":1253},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fanimating-gradients","Animating CSS Gradients: Smooth Colour Motion Without Jumps",{"path":1255,"title":1256},"\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":1258,"title":1259},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions","Color & Theme Transitions: Colour as Part of the Motion System",{"path":1261,"title":1262},"\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":1264,"title":1265},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fsmooth-theme-switching-transitions","Smooth Theme Switching: Crossfades, Circular Reveals and No Flash",{"path":1267,"title":1268},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1270,"title":1271},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1273,"title":1274},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Flayout-change-animations-at-container-breakpoints","Animating Changes at Container Breakpoints",{"path":1276,"title":1277},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries","Motion Driven by Container Style Queries",{"path":1279,"title":1280},"\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":1282,"title":1283},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":1285,"title":1286},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript","Controlling CSS Animations From JavaScript",{"path":1288,"title":1289},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1291,"title":1292},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui","Interruptible UI: CSS Transitions vs WAAPI",{"path":1294,"title":1295},"\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":1297,"title":1298},"\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":1201,"title":5},{"path":1301,"title":1302},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1304,"title":1305},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1307,"title":1308},"\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":1310,"title":1311},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components","Scoping Custom Properties to Components",{"path":1313,"title":1314},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1316,"title":1317},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1319,"title":1320},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions","Interrupted and Reversing Transitions: What Happens Mid-Flight",{"path":1322,"title":1323},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1325,"title":1326},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-delay-choreography","Choreographing Motion With transition-delay",{"path":1328,"title":1329},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties","The transition Shorthand and Multiple Properties",{"path":1331,"title":1332},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1334,"title":1335},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fanimating-dialog-open-and-close","Animating \u003Cdialog> Open and Close: Both Directions, No Library",{"path":1337,"title":1338},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fbackdrop-animations","Animating ::backdrop: Fades and Blurs Behind Dialogs and Popovers",{"path":1340,"title":1341},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations","Dialog & Popover Animations: Motion for the Top Layer",{"path":1343,"title":1344},"\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":1346,"title":1347},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fpopover-entry-and-exit-transitions","Popover Menus That Animate From Their Anchor",{"path":1349,"title":1350},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations","Choosing Animation Durations: How Long Motion Should Last",{"path":1352,"title":1353},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fcubic-bezier-overshoot-and-anticipation","Overshoot and Anticipation With cubic-bezier(): Motion With Character",{"path":1355,"title":1356},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fentry-vs-exit-easing","Entry vs Exit Easing: Different Curves for Arriving and Leaving",{"path":1358,"title":1359},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design","Easing & Motion Design: Making CSS Motion Feel Intentional",{"path":1361,"title":1362},"\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":1364,"title":1365},"\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":1367,"title":1368},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1370,"title":1371},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fbutton-press-and-active-states","Button Press and  States",{"path":1373,"title":1374},"\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":1376,"title":1377},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1379,"title":1380},"\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":1382,"title":1383},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1385,"title":1386},"\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":1388,"title":1389},"\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":1391,"title":1392},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1394,"title":1395},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-composition-and-stacking","Stacking Animations With animation-composition",{"path":1397,"title":1398},"\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":1400,"title":1401},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1403,"title":1404},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1406,"title":1407},"\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":1409,"title":1410},"\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":1412,"title":1413},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1415,"title":1416},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fmulti-step-keyframes-and-per-keyframe-easing","Multi-Step Keyframes and Per-Keyframe Easing",{"path":1418,"title":1419},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1421,"title":1422},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fanimating-box-shadow-and-filters-cheaply","Animating box-shadow and Filters Cheaply",{"path":1424,"title":1425},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcontain-property-for-animation-performance","The contain Property for Animation Performance",{"path":1427,"title":1428},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcss-triggers-layout-paint-composite","Layout, Paint and Composite: What Triggers What",{"path":1430,"title":1431},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1433,"title":1434},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1436,"title":1437},"\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":1439,"title":1440},"\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":1442,"title":1443},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1445,"title":1446},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1448,"title":1449},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-parallax-effects","Scroll-Driven Parallax Effects in CSS",{"path":1451,"title":1452},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1454,"title":1455},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1457,"title":1458},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Ftimeline-scope-for-cross-element-animations","timeline-scope for Cross-Element Animations",{"path":1460,"title":1461},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fview-timeline-and-animation-range","View Timelines and animation-range",{"path":1463,"title":1464},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fcross-document-view-transitions","Cross-Document View Transitions",{"path":1466,"title":1467},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1469,"title":1470},"\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":1472,"title":1473},"\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":1475,"title":1476},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-types-and-classes","View Transition Types and Classes",{"path":1478,"title":1479},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-for-list-reordering","View Transitions for List Reordering",{"path":1481,"title":1482},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":356,"title":1484},"Modern CSS Layouts & Micro-Interactions",{"path":1486,"title":1487},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1489,"title":1490},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1492,"title":1493},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-size-for-matching-widths","anchor-size(): Overlays That Match Their Trigger's Size",{"path":1495,"title":1496},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1498,"title":1499},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1501,"title":1502},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-light-dismiss-and-stacking","Popover Light Dismiss, Nesting and Stacking",{"path":1504,"title":1505},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fposition-area-grid-explained","position-area: The Anchor Placement Grid",{"path":1507,"title":1508},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fcontainer-query-polyfill-tradeoffs","Container Query Polyfills: What They Cost and When to Skip Them",{"path":1510,"title":1511},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1513,"title":1514},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1516,"title":1517},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1519,"title":1520},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fintrinsic-layout-fallbacks-without-queries","Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query",{"path":1522,"title":1523},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ftesting-fallbacks-without-old-browsers","Testing CSS Fallbacks Without an Old Browser",{"path":1525,"title":1526},"\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":1528,"title":1529},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-range-and-logic-operators","Container Query Range Syntax and Logic Operators",{"path":1531,"title":1532},"\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":1534,"title":1535},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1537,"title":1538},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1540,"title":1541},"\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":1543,"title":1544},"\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":1546,"title":1547},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1549,"title":1550},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1552,"title":1553},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1555,"title":1556},"\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":1558,"title":1559},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-auto-flow-dense-packing","grid-auto-flow: dense for Packed Layouts",{"path":1561,"title":1562},"\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":1564,"title":1565},"\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":1567,"title":1568},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1570,"title":1571},"\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":1573,"title":1574},"\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":1576,"title":1577},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1579,"title":1580},"\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":1582,"title":1583},"\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":1585,"title":1586},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-grow-and-flex-shrink-explained","flex-grow and flex-shrink Explained",{"path":1588,"title":1589},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-wrap-intrinsic-responsive-rows","Breakpoint-Free Responsive Rows With flex-wrap and flex-basis",{"path":1591,"title":1592},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflexbox-gap-and-spacing","Flexbox gap vs Margins: Spacing Items Without Edge Hacks",{"path":1594,"title":1595},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns","Flexbox Layout Patterns: One-Dimensional Layout for Real Components",{"path":1597,"title":1598},"\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":1600,"title":1601},"\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":1603,"title":1604},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fdebugging-clamp-values","Debugging clamp(): Values That Are Ignored, Stuck or Never Fluid",{"path":1606,"title":1607},"\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":1609,"title":1610},"\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":1612,"title":1613},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1615,"title":1616},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1618,"title":1619},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1621,"title":1622},"\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":1624,"title":1625},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1627,"title":1628},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1630,"title":1631},"\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":1633,"title":1634},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1636,"title":1637},"\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":1639,"title":1640},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1642,"title":1643},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fobject-fit-and-object-position","object-fit and object-position: Images That Fit Any Box",{"path":1645,"title":1646},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1648,"title":1649},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1651,"title":1652},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1654,"title":1655},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcss-scope-for-component-styles","@scope for Component Styles: Short Selectors That Cannot Leak",{"path":1657,"title":1658},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1660,"title":1661},"\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":1663,"title":1664},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fwriting-a-minimal-modern-reset","Writing a Minimal Modern CSS Reset: Every Line Justified",{"path":1666,"title":1667},"\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":1669,"title":1670},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fempty-and-loading-states-with-has","Empty and Loading States With ()",{"path":1672,"title":1673},"\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":1675,"title":1676},"\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":1678,"title":1679},"\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":1681,"title":1682},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has","Parent-Aware Layouts With :has(): Letting Containers React to Their Contents",{"path":1684,"title":1685},"\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":1687,"title":1688},"\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":1690,"title":1691},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1693,"title":1694},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":1696,"title":1697},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":1699,"title":1700},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":1702,"title":1703},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-hero-sections-with-container-queries","Responsive Hero Sections With Container Queries",{"path":1705,"title":1706},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":1708,"title":1709},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-pricing-tables","Responsive Pricing Tables: Aligned Features, a Clear Recommendation, Any Width",{"path":1711,"title":1712},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Ftabs-that-become-accordions","Tabs That Become an Accordion: One Component, Two Layouts",{"path":1714,"title":1715},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap","A CSS-Only Carousel With Scroll Snap",{"path":1717,"title":1718},"\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":1720,"title":1721},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts","Scroll Snap & Overflow Layouts: Designing Components That Scroll on Purpose",{"path":1723,"title":1724},"\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":1726,"title":1727},"\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":1729,"title":1730},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcombining-size-and-style-queries","Combining Size and Style Container Queries",{"path":1732,"title":1733},"\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":1735,"title":1736},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":1738,"title":1739},"\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":1741,"title":1742},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-component-variants","Component Variants With Style Queries: One Token, Many Looks",{"path":1744,"title":1745},"\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":1747,"title":1748},"\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":1750,"title":1751},"\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":1753,"title":1754},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout","Viewport Units & Mobile Layout: Designing for the Screen You Actually Get",{"path":1756,"title":1757},"\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":1759,"title":1760},"\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":1762,"title":1763},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fvirtual-keyboard-and-interactive-widget","Layouts That Survive the Virtual Keyboard",{"title":1765,"caption":1766,"height":1767,"html":1768,"css":1769},"Valid token, missing token, typo","Hover each button. The first uses its 250ms token, the second falls back to 600ms, and the third — with the token set to \"fast\" — has no transition at all.",150,"\n\u003Cdiv class=\"row\">\n  \u003Cbutton class=\"btn btn--token\" type=\"button\">Token: 250ms\u003C\u002Fbutton>\n  \u003Cbutton class=\"btn btn--missing\" type=\"button\">Missing: fallback\u003C\u002Fbutton>\n  \u003Cbutton class=\"btn btn--typo\" type=\"button\">Typo: no transition\u003C\u002Fbutton>\n\u003C\u002Fdiv>","\n.row { display: flex; gap: 1rem; flex-wrap: wrap; padding: 1.5rem 1rem; }\n.btn { padding: 0.75rem 1.25rem; border: 0; border-radius: 8px; background: #2563eb; color: #fff; font: inherit; cursor: pointer; transition: background-color 400ms ease-out, translate 400ms ease-out; transition-duration: var(--motion-duration, 600ms); }\n.btn:hover { background: #7c3aed; translate: 0 -4px; }\n.btn--token { --motion-duration: 250ms; }\n.btn--typo { --motion-duration: fast; }",1789717748504]