[{"data":1,"prerenderedAt":1906},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure":3,"content-all-pages":1643},{"id":4,"title":5,"body":6,"description":1625,"extension":1626,"meta":1627,"navigation":396,"path":1639,"seo":1640,"stem":1641,"__hash__":1642},"content\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure\u002Findex.md","CSS-Only Accordions and Disclosure Widgets with details and summary",{"type":7,"value":8,"toc":1615},"minimark",[9,13,40,43,46,51,73,85,87,91,97,234,236,240,243,247,599,1211,1233,1235,1239,1284,1304,1317,1319,1323,1331,1468,1474,1476,1480,1516,1518,1522,1542,1551,1562,1568,1570,1574,1611],[10,11,5],"h1",{"id":12},"css-only-accordions-and-disclosure-widgets-with-details-and-summary",[14,15,16,17,21,22,25,26,29,30,33,34,39],"p",{},"Accordions have been a JavaScript component for as long as component libraries have existed, largely for one reason: nobody could animate a panel to its natural height without measuring it in script first. That constraint is gone. The ",[18,19,20],"code",{},"\u003Cdetails>"," element gives you the toggle, its ",[18,23,24],{},"name"," attribute gives you exclusivity, ",[18,27,28],{},"::details-content"," gives you a box to animate, and intrinsic-size interpolation gives you the ",[18,31,32],{},"auto"," height. This page, part of the ",[35,36,38],"a",{"href":37},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002F","Keyframe Animation Patterns"," section, assembles all four into a production accordion with no script and no ARIA of your own.",[14,41,42],{},"The narrow scenario: a stacked set of FAQ or settings panels where opening one closes the others, each panel slides open to whatever height its content needs, and the whole thing is keyboard and screen-reader correct out of the box.",[44,45],"hr",{},[47,48,50],"h2",{"id":49},"why-the-native-element-beats-the-checkbox-hack","Why the native element beats the checkbox hack",[14,52,53,54,57,58,61,62,65,66,65,69,72],{},"The classic CSS-only disclosure is a visually hidden checkbox, a ",[18,55,56],{},"\u003Clabel>"," styled as a header, and a sibling panel revealed with ",[18,59,60],{},":checked ~ .panel",". It works, and for a decade it was the only option. It is also the wrong control. Assistive technology announces a checkbox — a control for selecting a value — where the user is actually expanding a region. Fixing that means adding ",[18,63,64],{},"role=\"button\"",", ",[18,67,68],{},"aria-expanded",[18,70,71],{},"aria-controls",", and a keyboard handler, at which point the \"no JavaScript\" claim is gone.",[14,74,75,77,78,81,82,84],{},[18,76,20],{}," and ",[18,79,80],{},"\u003Csummary>"," carry the correct semantics natively. The summary is focusable, responds to Enter and Space, exposes a disclosure widget with a managed expanded state, and the panel participates in find-in-page: searching for text inside a closed panel opens it. None of that is code you write or maintain. The remaining objection used to be visual — the element could not be animated — and that is precisely what the CSS below solves. The one case where a hand-rolled widget still wins is when the header must contain its own interactive controls, since interactive content inside ",[18,83,80],{}," is not reliably operable; put those controls inside the panel instead.",[44,86],{},[47,88,90],{"id":89},"anatomy-of-an-animated-details-element","Anatomy of an animated details element",[14,92,93,94,96],{},"The diagram shows what changes between the closed and open states. The summary box is always rendered; everything else lives inside a generated ",[18,95,28],{}," box whose block size is what actually animates.",[98,99,105,106,105,110,105,114,105,121,105,133,105,139,105,147,105,152,105,157,105,160,105,165,105,169,105,174,105,183,105,186,105,191,105,194,105,196,105,200,105,203,105,207,105,210,105,213,105,218],"svg",{"viewBox":100,"role":101,"ariaLabel":102,"xmlns":103,"style":104},"0 0 720 360","img","Closed and open details elements showing the details-content box growing from zero to auto height","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[107,108,109],"title",{},"Closed versus open details anatomy",[111,112,113],"desc",{},"Two panels comparing a closed details element whose content box has zero block size with an open one whose content box has an automatic block size.",[115,116,120],"text",{"x":117,"y":118,"style":119},"360","30","text-anchor:middle;fill:currentColor;font:700 18px sans-serif","What actually animates in a details element",[122,123],"rect",{"x":124,"y":125,"width":126,"height":127,"rx":128,"fill":129,"stroke":130,"strokeWidth":131,"opacity":132},"24","64","320","250","12","none","currentColor","1.5","0.45",[115,134,138],{"x":135,"y":136,"style":137},"184","92","text-anchor:middle;fill:currentColor;font:600 13px sans-serif","closed",[122,140],{"x":141,"y":142,"width":143,"height":144,"rx":145,"fill":129,"stroke":130,"strokeWidth":131,"opacity":146},"48","106","272","44","6","0.6",[115,148,151],{"x":135,"y":149,"style":150},"133","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","summary",[122,153],{"x":141,"y":154,"width":143,"height":155,"rx":156,"fill":129,"stroke":130,"strokeWidth":131,"opacity":146},"162","10","3",[115,158,28],{"x":135,"y":159,"style":150},"200",[115,161,164],{"x":135,"y":162,"style":163},"220","text-anchor:middle;fill:currentColor;font:11px sans-serif;opacity:0.75","block-size: 0",[115,166,168],{"x":135,"y":167,"style":163},"238","content-visibility: hidden",[115,170,173],{"x":135,"y":171,"style":172},"288","text-anchor:middle;fill:currentColor;font:11px sans-serif;opacity:0.7","panel is collapsed",[175,176],"line",{"x1":177,"y1":178,"x2":179,"y2":178,"stroke":180,"strokeWidth":181,"markerEnd":182},"346","188","372","#7aa2ff","2","url(#acc-arr)",[122,184],{"x":185,"y":125,"width":126,"height":127,"rx":128,"fill":129,"stroke":180,"strokeWidth":131},"376",[115,187,190],{"x":188,"y":136,"style":189},"536","text-anchor:middle;fill:#7aa2ff;font:600 13px sans-serif","open",[122,192],{"x":193,"y":142,"width":143,"height":144,"rx":145,"fill":129,"stroke":130,"strokeWidth":131,"opacity":146},"400",[115,195,151],{"x":188,"y":149,"style":150},[122,197],{"x":193,"y":154,"width":143,"height":198,"rx":145,"fill":180,"opacity":199},"94","0.2",[115,201,28],{"x":188,"y":202,"style":150},"192",[115,204,206],{"x":188,"y":205,"style":163},"212","block-size: auto",[115,208,209],{"x":188,"y":167,"style":163},"panel content flows here",[115,211,212],{"x":188,"y":171,"style":172},"height resolves to content",[115,214,217],{"x":117,"y":215,"style":216},"342","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.8","Keyword interpolation is what makes the 0 to auto step animatable.",[219,220,221,222,105],"defs",{},"\n    ",[223,224,229,230,221],"marker",{"id":225,"markerWidth":226,"markerHeight":226,"refX":227,"refY":228,"orient":32},"acc-arr","9","7","4","\n      ",[231,232],"path",{"d":233,"fill":130},"M0 0 L8 4 L0 8 z",[44,235],{},[47,237,239],{"id":238},"a-complete-working-implementation","A complete working implementation",[14,241,242],{},"Open a section in the demo, then open another one — the first closes itself, and each panel eases to the exact height its own text needs. Tab through it as well; the focus ring lands on the summary and Enter toggles it.",[244,245],"live-demo",{"name":246},"tk-details-accordion",[248,249,254],"pre",{"className":250,"code":251,"language":252,"meta":253,"style":253},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cdiv class=\"acc\">\n  \u003Cdetails class=\"acc__item\" name=\"faq\">\n    \u003Csummary class=\"acc__summary\">Does this need JavaScript?\u003C\u002Fsummary>\n    \u003Cdiv class=\"acc__body\">\n      \u003Cp>No. The \u003Ccode>details\u003C\u002Fcode> element toggles itself, and the open height is animated in CSS.\u003C\u002Fp>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdetails>\n\n  \u003Cdetails class=\"acc__item\" name=\"faq\">\n    \u003Csummary class=\"acc__summary\">What makes only one open at a time?\u003C\u002Fsummary>\n    \u003Cdiv class=\"acc__body\">\n      \u003Cp>Both elements share \u003Ccode>name=\"faq\"\u003C\u002Fcode>, so the browser closes the other one for you.\u003C\u002Fp>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdetails>\n\n  \u003Cdetails class=\"acc__item\" name=\"faq\">\n    \u003Csummary class=\"acc__summary\">Is it keyboard accessible?\u003C\u002Fsummary>\n    \u003Cdiv class=\"acc__body\">\n      \u003Cp>Yes — the summary is focusable and toggles with Enter or Space with no extra ARIA.\u003C\u002Fp>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdetails>\n\u003C\u002Fdiv>\n","html","",[18,255,256,282,308,330,346,371,381,391,398,419,439,454,478,487,496,501,522,542,557,571,580,589],{"__ignoreMap":253},[257,258,260,264,268,272,275,279],"span",{"class":175,"line":259},1,[257,261,263],{"class":262},"suds8","\u003C",[257,265,267],{"class":266},"sne4z","div",[257,269,271],{"class":270},"s-5SL"," class",[257,273,274],{"class":262},"=",[257,276,278],{"class":277},"sT6z2","\"acc\"",[257,280,281],{"class":262},">\n",[257,283,285,288,291,293,295,298,301,303,306],{"class":175,"line":284},2,[257,286,287],{"class":262},"  \u003C",[257,289,290],{"class":266},"details",[257,292,271],{"class":270},[257,294,274],{"class":262},[257,296,297],{"class":277},"\"acc__item\"",[257,299,300],{"class":270}," name",[257,302,274],{"class":262},[257,304,305],{"class":277},"\"faq\"",[257,307,281],{"class":262},[257,309,311,314,316,318,320,323,326,328],{"class":175,"line":310},3,[257,312,313],{"class":262},"    \u003C",[257,315,151],{"class":266},[257,317,271],{"class":270},[257,319,274],{"class":262},[257,321,322],{"class":277},"\"acc__summary\"",[257,324,325],{"class":262},">Does this need JavaScript?\u003C\u002F",[257,327,151],{"class":266},[257,329,281],{"class":262},[257,331,333,335,337,339,341,344],{"class":175,"line":332},4,[257,334,313],{"class":262},[257,336,267],{"class":266},[257,338,271],{"class":270},[257,340,274],{"class":262},[257,342,343],{"class":277},"\"acc__body\"",[257,345,281],{"class":262},[257,347,349,352,354,357,359,362,364,367,369],{"class":175,"line":348},5,[257,350,351],{"class":262},"      \u003C",[257,353,14],{"class":266},[257,355,356],{"class":262},">No. The \u003C",[257,358,18],{"class":266},[257,360,361],{"class":262},">details\u003C\u002F",[257,363,18],{"class":266},[257,365,366],{"class":262},"> element toggles itself, and the open height is animated in CSS.\u003C\u002F",[257,368,14],{"class":266},[257,370,281],{"class":262},[257,372,374,377,379],{"class":175,"line":373},6,[257,375,376],{"class":262},"    \u003C\u002F",[257,378,267],{"class":266},[257,380,281],{"class":262},[257,382,384,387,389],{"class":175,"line":383},7,[257,385,386],{"class":262},"  \u003C\u002F",[257,388,290],{"class":266},[257,390,281],{"class":262},[257,392,394],{"class":175,"line":393},8,[257,395,397],{"emptyLinePlaceholder":396},true,"\n",[257,399,401,403,405,407,409,411,413,415,417],{"class":175,"line":400},9,[257,402,287],{"class":262},[257,404,290],{"class":266},[257,406,271],{"class":270},[257,408,274],{"class":262},[257,410,297],{"class":277},[257,412,300],{"class":270},[257,414,274],{"class":262},[257,416,305],{"class":277},[257,418,281],{"class":262},[257,420,422,424,426,428,430,432,435,437],{"class":175,"line":421},10,[257,423,313],{"class":262},[257,425,151],{"class":266},[257,427,271],{"class":270},[257,429,274],{"class":262},[257,431,322],{"class":277},[257,433,434],{"class":262},">What makes only one open at a time?\u003C\u002F",[257,436,151],{"class":266},[257,438,281],{"class":262},[257,440,442,444,446,448,450,452],{"class":175,"line":441},11,[257,443,313],{"class":262},[257,445,267],{"class":266},[257,447,271],{"class":270},[257,449,274],{"class":262},[257,451,343],{"class":277},[257,453,281],{"class":262},[257,455,457,459,461,464,466,469,471,474,476],{"class":175,"line":456},12,[257,458,351],{"class":262},[257,460,14],{"class":266},[257,462,463],{"class":262},">Both elements share \u003C",[257,465,18],{"class":266},[257,467,468],{"class":262},">name=\"faq\"\u003C\u002F",[257,470,18],{"class":266},[257,472,473],{"class":262},">, so the browser closes the other one for you.\u003C\u002F",[257,475,14],{"class":266},[257,477,281],{"class":262},[257,479,481,483,485],{"class":175,"line":480},13,[257,482,376],{"class":262},[257,484,267],{"class":266},[257,486,281],{"class":262},[257,488,490,492,494],{"class":175,"line":489},14,[257,491,386],{"class":262},[257,493,290],{"class":266},[257,495,281],{"class":262},[257,497,499],{"class":175,"line":498},15,[257,500,397],{"emptyLinePlaceholder":396},[257,502,504,506,508,510,512,514,516,518,520],{"class":175,"line":503},16,[257,505,287],{"class":262},[257,507,290],{"class":266},[257,509,271],{"class":270},[257,511,274],{"class":262},[257,513,297],{"class":277},[257,515,300],{"class":270},[257,517,274],{"class":262},[257,519,305],{"class":277},[257,521,281],{"class":262},[257,523,525,527,529,531,533,535,538,540],{"class":175,"line":524},17,[257,526,313],{"class":262},[257,528,151],{"class":266},[257,530,271],{"class":270},[257,532,274],{"class":262},[257,534,322],{"class":277},[257,536,537],{"class":262},">Is it keyboard accessible?\u003C\u002F",[257,539,151],{"class":266},[257,541,281],{"class":262},[257,543,545,547,549,551,553,555],{"class":175,"line":544},18,[257,546,313],{"class":262},[257,548,267],{"class":266},[257,550,271],{"class":270},[257,552,274],{"class":262},[257,554,343],{"class":277},[257,556,281],{"class":262},[257,558,560,562,564,567,569],{"class":175,"line":559},19,[257,561,351],{"class":262},[257,563,14],{"class":266},[257,565,566],{"class":262},">Yes — the summary is focusable and toggles with Enter or Space with no extra ARIA.\u003C\u002F",[257,568,14],{"class":266},[257,570,281],{"class":262},[257,572,574,576,578],{"class":175,"line":573},20,[257,575,376],{"class":262},[257,577,267],{"class":266},[257,579,281],{"class":262},[257,581,583,585,587],{"class":175,"line":582},21,[257,584,386],{"class":262},[257,586,290],{"class":266},[257,588,281],{"class":262},[257,590,592,595,597],{"class":175,"line":591},22,[257,593,594],{"class":262},"\u003C\u002F",[257,596,267],{"class":266},[257,598,281],{"class":262},[248,600,604],{"className":601,"code":602,"language":603,"meta":253,"style":253},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F* Opt the subtree into interpolating to and from the auto keyword. *\u002F\n:root { interpolate-size: allow-keywords; }\n\n.acc { border: 1px solid currentColor; border-radius: 10px; overflow: hidden; }\n.acc__item + .acc__item { border-top: 1px solid currentColor; }\n\n\u002F* list-style: none removes the default disclosure triangle in most engines;\n   the ::-webkit-details-marker rule covers older WebKit builds. *\u002F\n.acc__summary {\n  list-style: none;\n  cursor: pointer;\n  padding: .8rem 1rem;\n  font-weight: 600;\n}\n.acc__summary::-webkit-details-marker { display: none; }\n.acc__summary::before {\n  content: \"\\25B8\";\n  display: inline-block;\n  margin-right: .55rem;\n  transition: rotate 220ms ease;\n}\n.acc__item[open] > .acc__summary::before { rotate: 90deg; }\n.acc__summary:focus-visible { outline: 2px solid currentColor; outline-offset: -2px; }\n\n\u002F* The generated wrapper around everything after the summary. Animating it\n   avoids wrapping the panel in an extra div purely to have a box to size. *\u002F\n.acc__item::details-content {\n  block-size: 0;\n  overflow: hidden;\n  opacity: 0;\n  transition:\n    block-size 260ms ease,\n    opacity 200ms ease,\n    content-visibility 260ms allow-discrete;\n}\n.acc__item[open]::details-content {\n  block-size: auto;\n  opacity: 1;\n}\n\n.acc__body { padding: 0 1rem 1rem; }\n.acc__body p { margin: 0; }\n\n@media (prefers-reduced-motion: reduce) {\n  .acc__item::details-content,\n  .acc__summary::before { transition: none; }\n}\n","css",[18,605,606,612,626,630,681,709,713,718,723,731,743,755,775,787,792,808,815,832,844,858,876,880,913,948,953,959,965,978,991,1003,1015,1023,1039,1053,1066,1071,1087,1098,1109,1114,1119,1144,1163,1168,1177,1189,1206],{"__ignoreMap":253},[257,607,608],{"class":175,"line":259},[257,609,611],{"class":610},"sLBg1","\u002F* Opt the subtree into interpolating to and from the auto keyword. *\u002F\n",[257,613,614,617,620,623],{"class":175,"line":284},[257,615,616],{"class":270},":root",[257,618,619],{"class":262}," { ",[257,621,622],{"class":270},"interpolate-size",[257,624,625],{"class":262},": allow-keywords; }\n",[257,627,628],{"class":175,"line":310},[257,629,397],{"emptyLinePlaceholder":396},[257,631,632,635,637,640,643,646,650,653,656,659,662,664,666,668,670,673,675,678],{"class":175,"line":332},[257,633,634],{"class":270},".acc",[257,636,619],{"class":262},[257,638,639],{"class":270},"border",[257,641,642],{"class":262},": ",[257,644,645],{"class":270},"1",[257,647,649],{"class":648},"sHUrx","px",[257,651,652],{"class":270}," solid",[257,654,655],{"class":270}," currentColor",[257,657,658],{"class":262},"; ",[257,660,661],{"class":270},"border-radius",[257,663,642],{"class":262},[257,665,155],{"class":270},[257,667,649],{"class":648},[257,669,658],{"class":262},[257,671,672],{"class":270},"overflow",[257,674,642],{"class":262},[257,676,677],{"class":270},"hidden",[257,679,680],{"class":262},"; }\n",[257,682,683,686,689,692,694,697,699,701,703,705,707],{"class":175,"line":348},[257,684,685],{"class":270},".acc__item",[257,687,688],{"class":648}," +",[257,690,691],{"class":270}," .acc__item",[257,693,619],{"class":262},[257,695,696],{"class":270},"border-top",[257,698,642],{"class":262},[257,700,645],{"class":270},[257,702,649],{"class":648},[257,704,652],{"class":270},[257,706,655],{"class":270},[257,708,680],{"class":262},[257,710,711],{"class":175,"line":373},[257,712,397],{"emptyLinePlaceholder":396},[257,714,715],{"class":175,"line":383},[257,716,717],{"class":610},"\u002F* list-style: none removes the default disclosure triangle in most engines;\n",[257,719,720],{"class":175,"line":393},[257,721,722],{"class":610},"   the ::-webkit-details-marker rule covers older WebKit builds. *\u002F\n",[257,724,725,728],{"class":175,"line":400},[257,726,727],{"class":270},".acc__summary",[257,729,730],{"class":262}," {\n",[257,732,733,736,738,740],{"class":175,"line":421},[257,734,735],{"class":270},"  list-style",[257,737,642],{"class":262},[257,739,129],{"class":270},[257,741,742],{"class":262},";\n",[257,744,745,748,750,753],{"class":175,"line":441},[257,746,747],{"class":270},"  cursor",[257,749,642],{"class":262},[257,751,752],{"class":270},"pointer",[257,754,742],{"class":262},[257,756,757,760,762,765,768,771,773],{"class":175,"line":456},[257,758,759],{"class":270},"  padding",[257,761,642],{"class":262},[257,763,764],{"class":270},".8",[257,766,767],{"class":648},"rem",[257,769,770],{"class":270}," 1",[257,772,767],{"class":648},[257,774,742],{"class":262},[257,776,777,780,782,785],{"class":175,"line":480},[257,778,779],{"class":270},"  font-weight",[257,781,642],{"class":262},[257,783,784],{"class":270},"600",[257,786,742],{"class":262},[257,788,789],{"class":175,"line":489},[257,790,791],{"class":262},"}\n",[257,793,794,797,799,802,804,806],{"class":175,"line":498},[257,795,796],{"class":270},".acc__summary::-webkit-details-marker",[257,798,619],{"class":262},[257,800,801],{"class":270},"display",[257,803,642],{"class":262},[257,805,129],{"class":270},[257,807,680],{"class":262},[257,809,810,813],{"class":175,"line":503},[257,811,812],{"class":270},".acc__summary::before",[257,814,730],{"class":262},[257,816,817,820,822,825,828,830],{"class":175,"line":524},[257,818,819],{"class":270},"  content",[257,821,642],{"class":262},[257,823,824],{"class":277},"\"",[257,826,827],{"class":648},"\\25B8",[257,829,824],{"class":277},[257,831,742],{"class":262},[257,833,834,837,839,842],{"class":175,"line":544},[257,835,836],{"class":270},"  display",[257,838,642],{"class":262},[257,840,841],{"class":270},"inline-block",[257,843,742],{"class":262},[257,845,846,849,851,854,856],{"class":175,"line":559},[257,847,848],{"class":270},"  margin-right",[257,850,642],{"class":262},[257,852,853],{"class":270},".55",[257,855,767],{"class":648},[257,857,742],{"class":262},[257,859,860,863,866,868,871,874],{"class":175,"line":573},[257,861,862],{"class":270},"  transition",[257,864,865],{"class":262},": rotate ",[257,867,162],{"class":270},[257,869,870],{"class":648},"ms",[257,872,873],{"class":270}," ease",[257,875,742],{"class":262},[257,877,878],{"class":175,"line":582},[257,879,791],{"class":262},[257,881,882,884,887,889,892,895,898,900,903,905,908,911],{"class":175,"line":591},[257,883,685],{"class":270},[257,885,886],{"class":262},"[",[257,888,190],{"class":270},[257,890,891],{"class":262},"] ",[257,893,894],{"class":648},">",[257,896,897],{"class":270}," .acc__summary::before",[257,899,619],{"class":262},[257,901,902],{"class":270},"rotate",[257,904,642],{"class":262},[257,906,907],{"class":270},"90",[257,909,910],{"class":648},"deg",[257,912,680],{"class":262},[257,914,916,919,921,924,926,928,930,932,934,936,939,941,944,946],{"class":175,"line":915},23,[257,917,918],{"class":270},".acc__summary:focus-visible",[257,920,619],{"class":262},[257,922,923],{"class":270},"outline",[257,925,642],{"class":262},[257,927,181],{"class":270},[257,929,649],{"class":648},[257,931,652],{"class":270},[257,933,655],{"class":270},[257,935,658],{"class":262},[257,937,938],{"class":270},"outline-offset",[257,940,642],{"class":262},[257,942,943],{"class":270},"-2",[257,945,649],{"class":648},[257,947,680],{"class":262},[257,949,951],{"class":175,"line":950},24,[257,952,397],{"emptyLinePlaceholder":396},[257,954,956],{"class":175,"line":955},25,[257,957,958],{"class":610},"\u002F* The generated wrapper around everything after the summary. Animating it\n",[257,960,962],{"class":175,"line":961},26,[257,963,964],{"class":610},"   avoids wrapping the panel in an extra div purely to have a box to size. *\u002F\n",[257,966,968,970,973,976],{"class":175,"line":967},27,[257,969,685],{"class":270},[257,971,972],{"class":262},"::",[257,974,975],{"class":266},"details-content",[257,977,730],{"class":262},[257,979,981,984,986,989],{"class":175,"line":980},28,[257,982,983],{"class":270},"  block-size",[257,985,642],{"class":262},[257,987,988],{"class":270},"0",[257,990,742],{"class":262},[257,992,994,997,999,1001],{"class":175,"line":993},29,[257,995,996],{"class":270},"  overflow",[257,998,642],{"class":262},[257,1000,677],{"class":270},[257,1002,742],{"class":262},[257,1004,1006,1009,1011,1013],{"class":175,"line":1005},30,[257,1007,1008],{"class":270},"  opacity",[257,1010,642],{"class":262},[257,1012,988],{"class":270},[257,1014,742],{"class":262},[257,1016,1018,1020],{"class":175,"line":1017},31,[257,1019,862],{"class":270},[257,1021,1022],{"class":262},":\n",[257,1024,1026,1029,1032,1034,1036],{"class":175,"line":1025},32,[257,1027,1028],{"class":262},"    block-size ",[257,1030,1031],{"class":270},"260",[257,1033,870],{"class":648},[257,1035,873],{"class":270},[257,1037,1038],{"class":262},",\n",[257,1040,1042,1045,1047,1049,1051],{"class":175,"line":1041},33,[257,1043,1044],{"class":262},"    opacity ",[257,1046,159],{"class":270},[257,1048,870],{"class":648},[257,1050,873],{"class":270},[257,1052,1038],{"class":262},[257,1054,1056,1059,1061,1063],{"class":175,"line":1055},34,[257,1057,1058],{"class":262},"    content-visibility ",[257,1060,1031],{"class":270},[257,1062,870],{"class":648},[257,1064,1065],{"class":262}," allow-discrete;\n",[257,1067,1069],{"class":175,"line":1068},35,[257,1070,791],{"class":262},[257,1072,1074,1076,1078,1080,1083,1085],{"class":175,"line":1073},36,[257,1075,685],{"class":270},[257,1077,886],{"class":262},[257,1079,190],{"class":270},[257,1081,1082],{"class":262},"]::",[257,1084,975],{"class":266},[257,1086,730],{"class":262},[257,1088,1090,1092,1094,1096],{"class":175,"line":1089},37,[257,1091,983],{"class":270},[257,1093,642],{"class":262},[257,1095,32],{"class":270},[257,1097,742],{"class":262},[257,1099,1101,1103,1105,1107],{"class":175,"line":1100},38,[257,1102,1008],{"class":270},[257,1104,642],{"class":262},[257,1106,645],{"class":270},[257,1108,742],{"class":262},[257,1110,1112],{"class":175,"line":1111},39,[257,1113,791],{"class":262},[257,1115,1117],{"class":175,"line":1116},40,[257,1118,397],{"emptyLinePlaceholder":396},[257,1120,1122,1125,1127,1130,1132,1134,1136,1138,1140,1142],{"class":175,"line":1121},41,[257,1123,1124],{"class":270},".acc__body",[257,1126,619],{"class":262},[257,1128,1129],{"class":270},"padding",[257,1131,642],{"class":262},[257,1133,988],{"class":270},[257,1135,770],{"class":270},[257,1137,767],{"class":648},[257,1139,770],{"class":270},[257,1141,767],{"class":648},[257,1143,680],{"class":262},[257,1145,1147,1149,1152,1154,1157,1159,1161],{"class":175,"line":1146},42,[257,1148,1124],{"class":270},[257,1150,1151],{"class":266}," p",[257,1153,619],{"class":262},[257,1155,1156],{"class":270},"margin",[257,1158,642],{"class":262},[257,1160,988],{"class":270},[257,1162,680],{"class":262},[257,1164,1166],{"class":175,"line":1165},43,[257,1167,397],{"emptyLinePlaceholder":396},[257,1169,1171,1174],{"class":175,"line":1170},44,[257,1172,1173],{"class":648},"@media",[257,1175,1176],{"class":262}," (prefers-reduced-motion: reduce) {\n",[257,1178,1180,1183,1185,1187],{"class":175,"line":1179},45,[257,1181,1182],{"class":270},"  .acc__item",[257,1184,972],{"class":262},[257,1186,975],{"class":266},[257,1188,1038],{"class":262},[257,1190,1192,1195,1197,1200,1202,1204],{"class":175,"line":1191},46,[257,1193,1194],{"class":270},"  .acc__summary::before",[257,1196,619],{"class":262},[257,1198,1199],{"class":270},"transition",[257,1201,642],{"class":262},[257,1203,129],{"class":270},[257,1205,680],{"class":262},[257,1207,1209],{"class":175,"line":1208},47,[257,1210,791],{"class":262},[14,1212,1213,1214,1217,1218,1220,1221,1224,1225,1227,1228,1232],{},"The ",[18,1215,1216],{},"content-visibility"," entry in the transition list matters more than it looks. A closed ",[18,1219,28],{}," box is skipped for rendering, and that is a discrete change — without ",[18,1222,1223],{},"allow-discrete"," holding it visible for the duration, the panel's contents would vanish on the first frame of the collapse and you would animate an empty box. The same keyword does the same job for ",[18,1226,801],{},", as covered in ",[35,1229,1231],{"href":1230},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete\u002F","transitioning display with allow-discrete",".",[44,1234],{},[47,1236,1238],{"id":1237},"the-key-technique-making-auto-an-interpolatable-value","The key technique: making auto an interpolatable value",[14,1240,1241,1244,1245,1247,1248,77,1251,1253,1254,1257,1258,1261,1262,65,1264,65,1267,1270,1271,1274,1275,1278,1279,77,1281,1283],{},[18,1242,1243],{},"height: auto"," has never been animatable because ",[18,1246,32],{}," is a keyword, not a length — there is no arithmetic that produces a value one third of the way between ",[18,1249,1250],{},"0px",[18,1252,32],{},". Two additions solve that. ",[18,1255,1256],{},"calc-size()"," is a sizing function that accepts an intrinsic keyword as its basis and lets you compute against it, which by itself gives the engine a numeric handle on the keyword. ",[18,1259,1260],{},"interpolate-size: allow-keywords"," is the opt-in that turns the handle on implicitly: set it on an ancestor and every ",[18,1263,32],{},[18,1265,1266],{},"min-content",[18,1268,1269],{},"max-content",", and ",[18,1272,1273],{},"fit-content"," value in that subtree becomes interpolatable, so an ordinary ",[18,1276,1277],{},"transition: block-size 260ms"," between ",[18,1280,988],{},[18,1282,32],{}," produces real intermediate heights.",[14,1285,1286,1287,1289,1290,1293,1294,1296,1297,1299,1300,1303],{},"The opt-in exists because animating to ",[18,1288,32],{}," is a behaviour change for pages written before it was possible — sheets that set ",[18,1291,1292],{},"transition: all"," on an element that also changes from a fixed height to ",[18,1295,32],{}," would suddenly start animating something that used to snap. Scoping it to ",[18,1298,616],{}," in a new codebase is fine; adding it to an existing one is worth testing. If you would rather not opt in globally, write the open state as ",[18,1301,1302],{},"block-size: calc-size(auto, size)"," on the specific rule instead and leave the rest of the document alone.",[14,1305,1306,1307,1309,1310,1312,1313,1316],{},"Exclusivity comes from a different mechanism entirely and needs no CSS: give every ",[18,1308,20],{}," in a group the same ",[18,1311,24],{}," value and the browser enforces one-open-at-a-time itself, closing the previously open sibling and firing its ",[18,1314,1315],{},"toggle"," event. Grouped elements do not have to be siblings in the DOM, which is convenient when the accordion rows are wrapped individually for layout.",[44,1318],{},[47,1320,1322],{"id":1321},"variation-a-disclosure-that-stays-open-on-large-screens","Variation: a disclosure that stays open on large screens",[14,1324,1325,1326,1330],{},"A common requirement is a filter panel that behaves as a collapsible disclosure on narrow layouts but is permanently open when there is room. Because the element responds to its own container rather than the viewport, this composes naturally with ",[35,1327,1329],{"href":1328},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-units-cqi-cqb-explained\u002F","container query units"," and container-based conditions.",[248,1332,1334],{"className":601,"code":1333,"language":603,"meta":253,"style":253},".filters { container-type: inline-size; }\n\n@container (min-width: 40rem) {\n  \u002F* Force the panel open and hide the toggle affordance entirely. *\u002F\n  .filters .acc__item::details-content {\n    block-size: auto;\n    opacity: 1;\n    content-visibility: visible;\n    transition: none;\n  }\n  .filters .acc__summary { cursor: default; }\n  .filters .acc__summary::before { display: none; }\n}\n",[18,1335,1336,1349,1353,1361,1366,1379,1390,1401,1413,1424,1429,1448,1464],{"__ignoreMap":253},[257,1337,1338,1341,1343,1346],{"class":175,"line":259},[257,1339,1340],{"class":270},".filters",[257,1342,619],{"class":262},[257,1344,1345],{"class":270},"container-type",[257,1347,1348],{"class":262},": inline-size; }\n",[257,1350,1351],{"class":175,"line":284},[257,1352,397],{"emptyLinePlaceholder":396},[257,1354,1355,1358],{"class":175,"line":310},[257,1356,1357],{"class":648},"@container",[257,1359,1360],{"class":262}," (min-width: 40rem) {\n",[257,1362,1363],{"class":175,"line":332},[257,1364,1365],{"class":610},"  \u002F* Force the panel open and hide the toggle affordance entirely. *\u002F\n",[257,1367,1368,1371,1373,1375,1377],{"class":175,"line":348},[257,1369,1370],{"class":270},"  .filters",[257,1372,691],{"class":270},[257,1374,972],{"class":262},[257,1376,975],{"class":266},[257,1378,730],{"class":262},[257,1380,1381,1384,1386,1388],{"class":175,"line":373},[257,1382,1383],{"class":270},"    block-size",[257,1385,642],{"class":262},[257,1387,32],{"class":270},[257,1389,742],{"class":262},[257,1391,1392,1395,1397,1399],{"class":175,"line":383},[257,1393,1394],{"class":270},"    opacity",[257,1396,642],{"class":262},[257,1398,645],{"class":270},[257,1400,742],{"class":262},[257,1402,1403,1406,1408,1411],{"class":175,"line":393},[257,1404,1405],{"class":270},"    content-visibility",[257,1407,642],{"class":262},[257,1409,1410],{"class":270},"visible",[257,1412,742],{"class":262},[257,1414,1415,1418,1420,1422],{"class":175,"line":400},[257,1416,1417],{"class":270},"    transition",[257,1419,642],{"class":262},[257,1421,129],{"class":270},[257,1423,742],{"class":262},[257,1425,1426],{"class":175,"line":421},[257,1427,1428],{"class":262},"  }\n",[257,1430,1431,1433,1436,1438,1441,1443,1446],{"class":175,"line":441},[257,1432,1370],{"class":270},[257,1434,1435],{"class":270}," .acc__summary",[257,1437,619],{"class":262},[257,1439,1440],{"class":270},"cursor",[257,1442,642],{"class":262},[257,1444,1445],{"class":270},"default",[257,1447,680],{"class":262},[257,1449,1450,1452,1454,1456,1458,1460,1462],{"class":175,"line":456},[257,1451,1370],{"class":270},[257,1453,897],{"class":270},[257,1455,619],{"class":262},[257,1457,801],{"class":270},[257,1459,642],{"class":262},[257,1461,129],{"class":270},[257,1463,680],{"class":262},[257,1465,1466],{"class":175,"line":480},[257,1467,791],{"class":262},[14,1469,1470,1471,1473],{},"This is a presentational override, not a semantic one — the element still reports itself as a disclosure. If the wide layout genuinely has no collapsed state, prefer rendering a plain heading and section for that breakpoint, and keep ",[18,1472,20],{}," for the layout where collapsing is real.",[44,1475],{},[47,1477,1479],{"id":1478},"browser-support-note","Browser support note",[14,1481,1482,77,1484,1486,1487,1489,1490,77,1492,1494,1495,1497,1498,1502,1503,1505,1506,1508,1509,1511,1512,1515],{},[18,1483,20],{},[18,1485,80],{}," themselves have been universally supported for many years, so the accordion's behaviour and semantics are never at risk. The newer pieces arrived separately, and they are not equally available. ",[18,1488,28],{}," is in every current engine — Chrome and Edge 131+, Firefox 143+, Safari 18.4+. ",[18,1491,622],{},[18,1493,1256],{},", which are what make the height animate to ",[18,1496,32],{},", remain ",[1499,1500,1501],"strong",{},"Chromium-only"," at Chrome and Edge 129+; neither Firefox nor Safari has shipped them. Treat the height animation as a Chromium-only enhancement rather than a baseline behaviour. Every one of these is additive: an engine that does not know ",[18,1504,28],{}," drops the rule as an unknown selector, one that does not know ",[18,1507,622],{}," drops the declaration, and one that does not know ",[18,1510,24],{}," simply lets both panels stay open. The accordion opens, closes, and reads correctly in all of those cases, which makes an ",[18,1513,1514],{},"@supports"," guard optional; add one only if the un-animated state needs different padding.",[44,1517],{},[47,1519,1521],{"id":1520},"faq","FAQ",[14,1523,1524,1527,1528,1530,1531,1533,1534,1536,1537,77,1539,1541],{},[1499,1525,1526],{},"Why can I now transition height to auto?","\nBecause ",[18,1529,1260],{}," opts an element and its descendants into interpolating intrinsic size keywords. Internally the browser resolves ",[18,1532,32],{}," into a ",[18,1535,1256],{}," value it knows how to interpolate, so a transition between ",[18,1538,988],{},[18,1540,32],{}," produces real intermediate heights instead of snapping.",[14,1543,1544,1547,1548,1550],{},[1499,1545,1546],{},"What does the name attribute on details do?","\nDetails elements sharing the same ",[18,1549,24],{}," value form an exclusive group, so opening one automatically closes the others. It replaces the JavaScript that accordion widgets traditionally used to enforce one-open-at-a-time behaviour, and the grouped elements do not need to be DOM siblings.",[14,1552,1553,1556,1557,77,1559,1561],{},[1499,1554,1555],{},"Is the native details element more accessible than a checkbox hack?","\nYes. ",[18,1558,20],{},[18,1560,80],{}," expose a real disclosure with a managed expanded state, keyboard operation, and find-in-page expansion for free. A hidden checkbox exposes a checkbox role instead and needs hand-written ARIA and scripting to describe the same interaction.",[14,1563,1564,1567],{},[1499,1565,1566],{},"What happens in a browser without ::details-content support?","\nThe rule is discarded as an unknown selector and the accordion still opens and closes instantly, because that behaviour comes from the element rather than from CSS. Only the height animation is lost.",[44,1569],{},[47,1571,1573],{"id":1572},"related","Related",[1575,1576,1577,1583,1590,1597,1604],"ul",{},[1578,1579,1580,1582],"li",{},[35,1581,38],{"href":37}," — the parent guide for script-free interactive components.",[1578,1584,1585,1589],{},[35,1586,1588],{"href":1587},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations\u002F","@starting-style entry animations"," — animate panels that are inserted rather than toggled.",[1578,1591,1592,1596],{},[35,1593,1595],{"href":1594},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-toggle-switches-and-checkboxes\u002F","CSS-only toggle switches and checkboxes"," — the sibling pattern for controls that really are checkboxes.",[1578,1598,1599,1603],{},[35,1600,1602],{"href":1601},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fcreating-accessible-focus-indicators\u002F","Creating accessible focus indicators"," — style the focus ring the summary element needs.",[1578,1605,1606,1610],{},[35,1607,1609],{"href":1608},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries\u002F","Responsive forms with container queries"," — the layout side of collapsible filter panels.",[1612,1613,1614],"style",{},"html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}",{"title":253,"searchDepth":284,"depth":284,"links":1616},[1617,1618,1619,1620,1621,1622,1623,1624],{"id":49,"depth":284,"text":50},{"id":89,"depth":284,"text":90},{"id":238,"depth":284,"text":239},{"id":1237,"depth":284,"text":1238},{"id":1321,"depth":284,"text":1322},{"id":1478,"depth":284,"text":1479},{"id":1520,"depth":284,"text":1521},{"id":1572,"depth":284,"text":1573},"Build an animated accordion without JavaScript: details and summary, a name attribute for exclusivity, ::details-content, and interpolate-size for auto height.","md",{"pageTitle":1628,"datePublished":1629,"dateModified":1629,"faq":1630},"CSS-only accordions and disclosure","2026-07-20",[1631,1633,1635,1637],{"q":1526,"a":1632},"Because interpolate-size: allow-keywords opts an element and its descendants into interpolating intrinsic size keywords. Internally the browser converts auto into a calc-size() value it knows how to interpolate, so a transition from 0 to auto produces real intermediate heights.",{"q":1546,"a":1634},"Details elements that share the same name value form an exclusive group, so opening one automatically closes the others. It replaces the JavaScript that accordion widgets traditionally used to enforce one-open-at-a-time behaviour.",{"q":1555,"a":1636},"Yes. Details and summary expose a real disclosure role with a managed expanded state, keyboard operation, and find-in-page expansion for free. A hidden checkbox exposes a checkbox role instead and needs hand-written ARIA to describe the same thing.",{"q":1566,"a":1638},"The rule is dropped as an unknown selector and the accordion still opens and closes instantly, because that behaviour comes from the element itself rather than from CSS. Only the height animation is lost.","\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure",{"title":5,"description":1625},"css-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure\u002Findex","-RyKNZFGCAYuMI7nF4W3TPwxauncxZlSzfkZ-1xHpO8",[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,1732,1735,1738,1741,1744,1747,1750,1753,1756,1759,1762,1765,1768,1771,1774,1777,1780,1783,1786,1789,1792,1795,1798,1801,1804,1807,1810,1813,1816,1819,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],{"path":1645,"title":1646},"\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":1648,"title":1649},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1651,"title":1652},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1654,"title":1655},"\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":1657,"title":1658},"\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":1660,"title":1661},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1663,"title":1664},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1666,"title":1667},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1669,"title":1670},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1672,"title":1673},"\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":1675,"title":1676},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":1678,"title":1679},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1681,"title":1682},"\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":1684,"title":1685},"\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":1687,"title":1688},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1690,"title":1691},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1693,"title":1694},"\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":1696,"title":1697},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1699,"title":1700},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1702,"title":1703},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1705,"title":1706},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1708,"title":1709},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1711,"title":1712},"\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":1714,"title":1715},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1717,"title":1718},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1720,"title":1721},"\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":1723,"title":1724},"\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":1726,"title":1727},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1729,"title":1730},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1639,"title":5},{"path":1733,"title":1734},"\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":1736,"title":1737},"\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":1739,"title":1740},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1742,"title":1743},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1745,"title":1746},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1748,"title":1749},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1751,"title":1752},"\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":1754,"title":1755},"\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":1757,"title":1758},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1760,"title":1761},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1763,"title":1764},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1766,"title":1767},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1769,"title":1770},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1772,"title":1773},"\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":1775,"title":1776},"\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":1778,"title":1779},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":1781,"title":1782},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":1784,"title":1785},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1787,"title":1788},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1790,"title":1791},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1793,"title":1794},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1796,"title":1797},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1799,"title":1800},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1802,"title":1803},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1805,"title":1806},"\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":1808,"title":1809},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1811,"title":1812},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1814,"title":1815},"\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":1817,"title":1818},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1820,"title":1821},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1823,"title":1824},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1826,"title":1827},"\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":1829,"title":1830},"\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":1832,"title":1833},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1835,"title":1836},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1838,"title":1839},"\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":1841,"title":1842},"\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":1844,"title":1845},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1847,"title":1848},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1850,"title":1851},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1853,"title":1854},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1856,"title":1857},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1859,"title":1860},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1862,"title":1863},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1865,"title":1866},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1868,"title":1869},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1871,"title":1872},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1874,"title":1875},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1877,"title":1878},"\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":1880,"title":1881},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1883,"title":1884},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":1886,"title":1887},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":1889,"title":1890},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":1892,"title":1893},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":1895,"title":1896},"\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":1898,"title":1899},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":1901,"title":1902},"\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":1904,"title":1905},"\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",1784566157917]