[{"data":1,"prerenderedAt":2075},["ShallowReactive",2],{"page-\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts\u002F":3,"content-all-pages":1814},{"id":4,"title":5,"body":6,"description":1794,"extension":1795,"meta":1796,"navigation":362,"path":1810,"seo":1811,"stem":1812,"__hash__":1813},"content\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts\u002Findex.md","Container Query Sidebar Layouts That Travel Between Contexts",{"type":7,"value":8,"toc":1784},"minimark",[9,13,28,33,41,49,56,154,157,161,164,168,1376,1394,1396,1400,1406,1422,1444,1446,1450,1461,1466,1482,1485,1487,1491,1501,1622,1635,1637,1641,1663,1677,1679,1683,1692,1706,1729,1742,1746,1781],[10,11,5],"h1",{"id":12},"container-query-sidebar-layouts-that-travel-between-contexts",[14,15,16,17,22,23,27],"p",{},"A sidebar-and-main pair is the layout most likely to be built twice. The first version lives on a full-width page and switches to a single column at a viewport breakpoint. Then someone drops the same component into a modal, or into the right-hand third of a dashboard, and the viewport is still 1440px wide while the component has 320px to work with — so the two-column rule fires and the sidebar squeezes the main column into a ribbon. This page builds the pair once, as a self-measuring component, following the patterns in ",[18,19,21],"a",{"href":20},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002F","responsive component patterns"," and the wider approach set out in ",[18,24,26],{"href":25},"\u002Fmastering-container-queries-responsive-layouts\u002F","Mastering Container Queries & Responsive Layouts",". The hard part is not the two-column rule; it is collapsing the sidebar into a horizontal strip without disturbing the order a keyboard or screen reader user moves through.",[29,30,32],"h2",{"id":31},"why-the-container-not-the-viewport","Why the container, not the viewport",[14,34,35,36,40],{},"The viewport is a property of the window. The available inline size is a property of the slot the component was placed in. Those two numbers agree only in the special case of a full-bleed page section, and a component library exists precisely because components get placed in slots you did not anticipate. A media query encodes an assumption about the page; a ",[37,38,39],"code",{},"@container"," rule encodes a fact about the box.",[14,42,43,44,48],{},"There is a second, quieter reason. A viewport breakpoint forces every instance on the page to switch at the same moment. If a dashboard shows three of these panels at different widths, that is wrong for at least two of them. Container queries let each instance answer independently, which is the same reasoning behind ",[18,45,47],{"href":46},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables\u002F","container query data tables"," collapsing columns per table rather than per page.",[14,50,51,52,55],{},"The tradeoff is real and worth naming. The queried element cannot be the container — an element cannot query its own size, because the size it would report is the size the query is about to change. So you pay one wrapper element per component. That wrapper also needs a resolvable inline size from its own parent; a container inside a ",[37,53,54],{},"float"," or an unconstrained absolutely positioned box may measure zero and quietly never match anything.",[57,58,64,65,64,69,64,73,64,80,64,86,64,98,64,107,64,112,64,117,64,121,64,125,64,128,64,133,64,138,64,141,64,145,64,149],"svg",{"viewBox":59,"role":60,"ariaLabel":61,"xmlns":62,"style":63},"0 0 720 330","img","The same sidebar component shown as a stacked strip in a narrow container and as two columns in a wide container","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[66,67,68],"title",{},"One component, two arrangements, one DOM order",[70,71,72],"desc",{},"In a narrow container the sidebar sits above the main region as a horizontal strip; in a wide container it becomes a left-hand column. The markup is identical in both.",[74,75,79],"text",{"x":76,"y":77,"style":78},"360","28","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","threshold: 34rem of container width",[74,81,85],{"x":82,"y":83,"style":84},"175","58","text-anchor:middle;fill:currentColor;font:600 13px sans-serif","narrow container",[87,88],"rect",{"x":89,"y":90,"width":91,"height":92,"rx":93,"fill":94,"stroke":95,"strokeWidth":96,"opacity":97},"30","70","290","200","10","none","currentColor","1.5","0.55",[87,99],{"x":100,"y":101,"width":102,"height":103,"rx":104,"fill":105,"opacity":106},"52","92","246","42","6","#7aa2ff","0.22",[74,108,111],{"x":82,"y":109,"style":110},"118","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.9","sidebar strip",[87,113],{"x":100,"y":114,"width":102,"height":115,"rx":104,"fill":95,"opacity":116},"146","104","0.12",[74,118,120],{"x":82,"y":119,"style":110},"203","main region",[74,122,124],{"x":123,"y":83,"style":84},"545","wide container",[87,126],{"x":127,"y":90,"width":91,"height":92,"rx":93,"fill":94,"stroke":95,"strokeWidth":96,"opacity":97},"400",[87,129],{"x":130,"y":101,"width":131,"height":132,"rx":104,"fill":105,"opacity":106},"418","96","158",[74,134,137],{"x":135,"y":136,"style":110},"466","176","sidebar",[87,139],{"x":140,"y":101,"width":114,"height":132,"rx":104,"fill":95,"opacity":116},"526",[74,142,144],{"x":143,"y":136,"style":110},"599","main",[74,146,148],{"x":76,"y":136,"style":147},"text-anchor:middle;fill:currentColor;font:18px sans-serif;opacity:0.6","→",[74,150,153],{"x":76,"y":151,"style":152},"306","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.75","Sidebar precedes main in the DOM in both states.",[155,156],"hr",{},[29,158,160],{"id":159},"the-complete-component","The complete component",[14,162,163],{},"Drag the frame narrower and watch two separate thresholds fire: the two-column grid dissolves first, then the facet chips stop sitting side by side.",[165,166],"live-demo",{"name":167},"lp2-sidebar-collapse",[169,170,175],"pre",{"className":171,"code":172,"language":173,"meta":174,"style":174},"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>Container-driven sidebar\u003C\u002Ftitle>\n\u003Cstyle>\n  body { margin: 0; padding: 1rem; font: 16px\u002F1.5 system-ui, sans-serif; }\n\n  \u002F* The wrapper is the container. The grid lives on it too, which is fine:\n     container-type: inline-size only contains size and layout, not children's\n     participation in the wrapper's own formatting context. *\u002F\n  .pane { container: pane \u002F inline-size; }\n\n  .pane__side,\n  .pane__main {\n    border: 1px solid #d4d4d8;\n    border-radius: 10px;\n    padding: 0.85rem 1rem;\n  }\n\n  \u002F* Single-column base. Every browser gets this, including ones that never\n     evaluate the @container rules below. *\u002F\n  .pane__side { margin-block-end: 0.75rem; }\n\n  .side__title,\n  .main__title {\n    margin: 0 0 0.5rem;\n    font-size: 0.8rem;\n    letter-spacing: 0.08em;\n    text-transform: uppercase;\n    opacity: 0.7;\n  }\n\n  .side__facets {\n    list-style: none;\n    margin: 0;\n    padding: 0;\n    display: flex;\n    flex-wrap: wrap;\n    gap: 0.4rem;\n  }\n\n  .facet {\n    border: 1px solid #d4d4d8;\n    border-radius: 999px;\n    padding: 0.25rem 0.7rem;\n    font-size: 0.85rem;\n  }\n\n  .main__body { margin: 0; }\n\n  \u002F* Very narrow: a wrapping row of chips reads as noise, so give each its\n     own line. This threshold is about the strip's contents, not the pair. *\u002F\n  @container pane (max-width: 22rem) {\n    .side__facets { flex-direction: column; align-items: stretch; }\n    .facet { text-align: center; }\n  }\n\n  \u002F* Enough room for two columns. minmax(0, 1fr) on the main track stops a\n     long unbreakable string from pushing the column past the container —\n     the default minimum of a grid track is auto, i.e. min-content. *\u002F\n  @container pane (min-width: 34rem) {\n    .pane {\n      display: grid;\n      grid-template-columns: 14rem minmax(0, 1fr);\n      gap: 0.75rem;\n      align-items: start;\n    }\n    .pane__side { margin-block-end: 0; }\n    .side__facets { flex-direction: column; align-items: stretch; }\n  }\n\u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Cdiv class=\"pane\">\n    \u003Caside class=\"pane__side\" aria-labelledby=\"facets-title\">\n      \u003Ch2 class=\"side__title\" id=\"facets-title\">Filters\u003C\u002Fh2>\n      \u003Cul class=\"side__facets\">\n        \u003Cli class=\"facet\">In stock\u003C\u002Fli>\n        \u003Cli class=\"facet\">Under $50\u003C\u002Fli>\n        \u003Cli class=\"facet\">Free returns\u003C\u002Fli>\n      \u003C\u002Ful>\n    \u003C\u002Faside>\n    \u003Carticle class=\"pane__main\" aria-labelledby=\"results-title\">\n      \u003Ch2 class=\"main__title\" id=\"results-title\">Results\u003C\u002Fh2>\n      \u003Cp class=\"main__body\">The sidebar never asks how wide the window is. It asks\n      how wide this pane is, so the same markup works full-bleed, in a modal, or\n      in a narrow column.\u003C\u002Fp>\n    \u003C\u002Farticle>\n  \u003C\u002Fdiv>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html","",[37,176,177,197,217,227,245,270,284,294,357,364,371,377,383,397,402,411,420,441,455,475,481,486,492,498,517,522,530,538,558,573,589,602,615,620,625,633,645,656,667,680,693,708,713,718,726,743,757,776,789,794,799,815,820,826,832,841,869,887,892,897,903,909,915,923,931,944,975,989,1002,1008,1024,1047,1052,1062,1071,1081,1100,1126,1155,1172,1195,1215,1235,1245,1255,1279,1306,1323,1329,1339,1348,1358,1367],{"__ignoreMap":174},[178,179,182,186,190,194],"span",{"class":180,"line":181},"line",1,[178,183,185],{"class":184},"suds8","\u003C!",[178,187,189],{"class":188},"sne4z","DOCTYPE",[178,191,193],{"class":192},"s-5SL"," html",[178,195,196],{"class":184},">\n",[178,198,200,203,205,208,211,215],{"class":180,"line":199},2,[178,201,202],{"class":184},"\u003C",[178,204,173],{"class":188},[178,206,207],{"class":192}," lang",[178,209,210],{"class":184},"=",[178,212,214],{"class":213},"sT6z2","\"en\"",[178,216,196],{"class":184},[178,218,220,222,225],{"class":180,"line":219},3,[178,221,202],{"class":184},[178,223,224],{"class":188},"head",[178,226,196],{"class":184},[178,228,230,232,235,238,240,243],{"class":180,"line":229},4,[178,231,202],{"class":184},[178,233,234],{"class":188},"meta",[178,236,237],{"class":192}," charset",[178,239,210],{"class":184},[178,241,242],{"class":213},"\"utf-8\"",[178,244,196],{"class":184},[178,246,248,250,252,255,257,260,263,265,268],{"class":180,"line":247},5,[178,249,202],{"class":184},[178,251,234],{"class":188},[178,253,254],{"class":192}," name",[178,256,210],{"class":184},[178,258,259],{"class":213},"\"viewport\"",[178,261,262],{"class":192}," content",[178,264,210],{"class":184},[178,266,267],{"class":213},"\"width=device-width, initial-scale=1\"",[178,269,196],{"class":184},[178,271,273,275,277,280,282],{"class":180,"line":272},6,[178,274,202],{"class":184},[178,276,66],{"class":188},[178,278,279],{"class":184},">Container-driven sidebar\u003C\u002F",[178,281,66],{"class":188},[178,283,196],{"class":184},[178,285,287,289,292],{"class":180,"line":286},7,[178,288,202],{"class":184},[178,290,291],{"class":188},"style",[178,293,196],{"class":184},[178,295,297,300,303,306,309,312,315,318,320,323,327,329,332,334,337,340,343,345,348,351,354],{"class":180,"line":296},8,[178,298,299],{"class":188},"  body",[178,301,302],{"class":184}," { ",[178,304,305],{"class":192},"margin",[178,307,308],{"class":184},": ",[178,310,311],{"class":192},"0",[178,313,314],{"class":184},"; ",[178,316,317],{"class":192},"padding",[178,319,308],{"class":184},[178,321,322],{"class":192},"1",[178,324,326],{"class":325},"sHUrx","rem",[178,328,314],{"class":184},[178,330,331],{"class":192},"font",[178,333,308],{"class":184},[178,335,336],{"class":192},"16",[178,338,339],{"class":325},"px",[178,341,342],{"class":184},"\u002F",[178,344,96],{"class":192},[178,346,347],{"class":192}," system-ui",[178,349,350],{"class":184},", ",[178,352,353],{"class":192},"sans-serif",[178,355,356],{"class":184},"; }\n",[178,358,360],{"class":180,"line":359},9,[178,361,363],{"emptyLinePlaceholder":362},true,"\n",[178,365,367],{"class":180,"line":366},10,[178,368,370],{"class":369},"sLBg1","  \u002F* The wrapper is the container. The grid lives on it too, which is fine:\n",[178,372,374],{"class":180,"line":373},11,[178,375,376],{"class":369},"     container-type: inline-size only contains size and layout, not children's\n",[178,378,380],{"class":180,"line":379},12,[178,381,382],{"class":369},"     participation in the wrapper's own formatting context. *\u002F\n",[178,384,386,389,391,394],{"class":180,"line":385},13,[178,387,388],{"class":192},"  .pane",[178,390,302],{"class":184},[178,392,393],{"class":192},"container",[178,395,396],{"class":184},": pane \u002F inline-size; }\n",[178,398,400],{"class":180,"line":399},14,[178,401,363],{"emptyLinePlaceholder":362},[178,403,405,408],{"class":180,"line":404},15,[178,406,407],{"class":192},"  .pane__side",[178,409,410],{"class":184},",\n",[178,412,414,417],{"class":180,"line":413},16,[178,415,416],{"class":192},"  .pane__main",[178,418,419],{"class":184}," {\n",[178,421,423,426,428,430,432,435,438],{"class":180,"line":422},17,[178,424,425],{"class":192},"    border",[178,427,308],{"class":184},[178,429,322],{"class":192},[178,431,339],{"class":325},[178,433,434],{"class":192}," solid",[178,436,437],{"class":192}," #d4d4d8",[178,439,440],{"class":184},";\n",[178,442,444,447,449,451,453],{"class":180,"line":443},18,[178,445,446],{"class":192},"    border-radius",[178,448,308],{"class":184},[178,450,93],{"class":192},[178,452,339],{"class":325},[178,454,440],{"class":184},[178,456,458,461,463,466,468,471,473],{"class":180,"line":457},19,[178,459,460],{"class":192},"    padding",[178,462,308],{"class":184},[178,464,465],{"class":192},"0.85",[178,467,326],{"class":325},[178,469,470],{"class":192}," 1",[178,472,326],{"class":325},[178,474,440],{"class":184},[178,476,478],{"class":180,"line":477},20,[178,479,480],{"class":184},"  }\n",[178,482,484],{"class":180,"line":483},21,[178,485,363],{"emptyLinePlaceholder":362},[178,487,489],{"class":180,"line":488},22,[178,490,491],{"class":369},"  \u002F* Single-column base. Every browser gets this, including ones that never\n",[178,493,495],{"class":180,"line":494},23,[178,496,497],{"class":369},"     evaluate the @container rules below. *\u002F\n",[178,499,501,503,505,508,510,513,515],{"class":180,"line":500},24,[178,502,407],{"class":192},[178,504,302],{"class":184},[178,506,507],{"class":192},"margin-block-end",[178,509,308],{"class":184},[178,511,512],{"class":192},"0.75",[178,514,326],{"class":325},[178,516,356],{"class":184},[178,518,520],{"class":180,"line":519},25,[178,521,363],{"emptyLinePlaceholder":362},[178,523,525,528],{"class":180,"line":524},26,[178,526,527],{"class":192},"  .side__title",[178,529,410],{"class":184},[178,531,533,536],{"class":180,"line":532},27,[178,534,535],{"class":192},"  .main__title",[178,537,419],{"class":184},[178,539,541,544,546,548,551,554,556],{"class":180,"line":540},28,[178,542,543],{"class":192},"    margin",[178,545,308],{"class":184},[178,547,311],{"class":192},[178,549,550],{"class":192}," 0",[178,552,553],{"class":192}," 0.5",[178,555,326],{"class":325},[178,557,440],{"class":184},[178,559,561,564,566,569,571],{"class":180,"line":560},29,[178,562,563],{"class":192},"    font-size",[178,565,308],{"class":184},[178,567,568],{"class":192},"0.8",[178,570,326],{"class":325},[178,572,440],{"class":184},[178,574,576,579,581,584,587],{"class":180,"line":575},30,[178,577,578],{"class":192},"    letter-spacing",[178,580,308],{"class":184},[178,582,583],{"class":192},"0.08",[178,585,586],{"class":325},"em",[178,588,440],{"class":184},[178,590,592,595,597,600],{"class":180,"line":591},31,[178,593,594],{"class":192},"    text-transform",[178,596,308],{"class":184},[178,598,599],{"class":192},"uppercase",[178,601,440],{"class":184},[178,603,605,608,610,613],{"class":180,"line":604},32,[178,606,607],{"class":192},"    opacity",[178,609,308],{"class":184},[178,611,612],{"class":192},"0.7",[178,614,440],{"class":184},[178,616,618],{"class":180,"line":617},33,[178,619,480],{"class":184},[178,621,623],{"class":180,"line":622},34,[178,624,363],{"emptyLinePlaceholder":362},[178,626,628,631],{"class":180,"line":627},35,[178,629,630],{"class":192},"  .side__facets",[178,632,419],{"class":184},[178,634,636,639,641,643],{"class":180,"line":635},36,[178,637,638],{"class":192},"    list-style",[178,640,308],{"class":184},[178,642,94],{"class":192},[178,644,440],{"class":184},[178,646,648,650,652,654],{"class":180,"line":647},37,[178,649,543],{"class":192},[178,651,308],{"class":184},[178,653,311],{"class":192},[178,655,440],{"class":184},[178,657,659,661,663,665],{"class":180,"line":658},38,[178,660,460],{"class":192},[178,662,308],{"class":184},[178,664,311],{"class":192},[178,666,440],{"class":184},[178,668,670,673,675,678],{"class":180,"line":669},39,[178,671,672],{"class":192},"    display",[178,674,308],{"class":184},[178,676,677],{"class":192},"flex",[178,679,440],{"class":184},[178,681,683,686,688,691],{"class":180,"line":682},40,[178,684,685],{"class":192},"    flex-wrap",[178,687,308],{"class":184},[178,689,690],{"class":192},"wrap",[178,692,440],{"class":184},[178,694,696,699,701,704,706],{"class":180,"line":695},41,[178,697,698],{"class":192},"    gap",[178,700,308],{"class":184},[178,702,703],{"class":192},"0.4",[178,705,326],{"class":325},[178,707,440],{"class":184},[178,709,711],{"class":180,"line":710},42,[178,712,480],{"class":184},[178,714,716],{"class":180,"line":715},43,[178,717,363],{"emptyLinePlaceholder":362},[178,719,721,724],{"class":180,"line":720},44,[178,722,723],{"class":192},"  .facet",[178,725,419],{"class":184},[178,727,729,731,733,735,737,739,741],{"class":180,"line":728},45,[178,730,425],{"class":192},[178,732,308],{"class":184},[178,734,322],{"class":192},[178,736,339],{"class":325},[178,738,434],{"class":192},[178,740,437],{"class":192},[178,742,440],{"class":184},[178,744,746,748,750,753,755],{"class":180,"line":745},46,[178,747,446],{"class":192},[178,749,308],{"class":184},[178,751,752],{"class":192},"999",[178,754,339],{"class":325},[178,756,440],{"class":184},[178,758,760,762,764,767,769,772,774],{"class":180,"line":759},47,[178,761,460],{"class":192},[178,763,308],{"class":184},[178,765,766],{"class":192},"0.25",[178,768,326],{"class":325},[178,770,771],{"class":192}," 0.7",[178,773,326],{"class":325},[178,775,440],{"class":184},[178,777,779,781,783,785,787],{"class":180,"line":778},48,[178,780,563],{"class":192},[178,782,308],{"class":184},[178,784,465],{"class":192},[178,786,326],{"class":325},[178,788,440],{"class":184},[178,790,792],{"class":180,"line":791},49,[178,793,480],{"class":184},[178,795,797],{"class":180,"line":796},50,[178,798,363],{"emptyLinePlaceholder":362},[178,800,802,805,807,809,811,813],{"class":180,"line":801},51,[178,803,804],{"class":192},"  .main__body",[178,806,302],{"class":184},[178,808,305],{"class":192},[178,810,308],{"class":184},[178,812,311],{"class":192},[178,814,356],{"class":184},[178,816,818],{"class":180,"line":817},52,[178,819,363],{"emptyLinePlaceholder":362},[178,821,823],{"class":180,"line":822},53,[178,824,825],{"class":369},"  \u002F* Very narrow: a wrapping row of chips reads as noise, so give each its\n",[178,827,829],{"class":180,"line":828},54,[178,830,831],{"class":369},"     own line. This threshold is about the strip's contents, not the pair. *\u002F\n",[178,833,835,838],{"class":180,"line":834},55,[178,836,837],{"class":325},"  @container",[178,839,840],{"class":184}," pane (max-width: 22rem) {\n",[178,842,844,847,849,852,854,857,859,862,864,867],{"class":180,"line":843},56,[178,845,846],{"class":192},"    .side__facets",[178,848,302],{"class":184},[178,850,851],{"class":192},"flex-direction",[178,853,308],{"class":184},[178,855,856],{"class":192},"column",[178,858,314],{"class":184},[178,860,861],{"class":192},"align-items",[178,863,308],{"class":184},[178,865,866],{"class":192},"stretch",[178,868,356],{"class":184},[178,870,872,875,877,880,882,885],{"class":180,"line":871},57,[178,873,874],{"class":192},"    .facet",[178,876,302],{"class":184},[178,878,879],{"class":192},"text-align",[178,881,308],{"class":184},[178,883,884],{"class":192},"center",[178,886,356],{"class":184},[178,888,890],{"class":180,"line":889},58,[178,891,480],{"class":184},[178,893,895],{"class":180,"line":894},59,[178,896,363],{"emptyLinePlaceholder":362},[178,898,900],{"class":180,"line":899},60,[178,901,902],{"class":369},"  \u002F* Enough room for two columns. minmax(0, 1fr) on the main track stops a\n",[178,904,906],{"class":180,"line":905},61,[178,907,908],{"class":369},"     long unbreakable string from pushing the column past the container —\n",[178,910,912],{"class":180,"line":911},62,[178,913,914],{"class":369},"     the default minimum of a grid track is auto, i.e. min-content. *\u002F\n",[178,916,918,920],{"class":180,"line":917},63,[178,919,837],{"class":325},[178,921,922],{"class":184}," pane (min-width: 34rem) {\n",[178,924,926,929],{"class":180,"line":925},64,[178,927,928],{"class":192},"    .pane",[178,930,419],{"class":184},[178,932,934,937,939,942],{"class":180,"line":933},65,[178,935,936],{"class":192},"      display",[178,938,308],{"class":184},[178,940,941],{"class":192},"grid",[178,943,440],{"class":184},[178,945,947,950,952,955,957,960,963,965,967,969,972],{"class":180,"line":946},66,[178,948,949],{"class":192},"      grid-template-columns",[178,951,308],{"class":184},[178,953,954],{"class":192},"14",[178,956,326],{"class":325},[178,958,959],{"class":192}," minmax",[178,961,962],{"class":184},"(",[178,964,311],{"class":192},[178,966,350],{"class":184},[178,968,322],{"class":192},[178,970,971],{"class":325},"fr",[178,973,974],{"class":184},");\n",[178,976,978,981,983,985,987],{"class":180,"line":977},67,[178,979,980],{"class":192},"      gap",[178,982,308],{"class":184},[178,984,512],{"class":192},[178,986,326],{"class":325},[178,988,440],{"class":184},[178,990,992,995,997,1000],{"class":180,"line":991},68,[178,993,994],{"class":192},"      align-items",[178,996,308],{"class":184},[178,998,999],{"class":192},"start",[178,1001,440],{"class":184},[178,1003,1005],{"class":180,"line":1004},69,[178,1006,1007],{"class":184},"    }\n",[178,1009,1011,1014,1016,1018,1020,1022],{"class":180,"line":1010},70,[178,1012,1013],{"class":192},"    .pane__side",[178,1015,302],{"class":184},[178,1017,507],{"class":192},[178,1019,308],{"class":184},[178,1021,311],{"class":192},[178,1023,356],{"class":184},[178,1025,1027,1029,1031,1033,1035,1037,1039,1041,1043,1045],{"class":180,"line":1026},71,[178,1028,846],{"class":192},[178,1030,302],{"class":184},[178,1032,851],{"class":192},[178,1034,308],{"class":184},[178,1036,856],{"class":192},[178,1038,314],{"class":184},[178,1040,861],{"class":192},[178,1042,308],{"class":184},[178,1044,866],{"class":192},[178,1046,356],{"class":184},[178,1048,1050],{"class":180,"line":1049},72,[178,1051,480],{"class":184},[178,1053,1055,1058,1060],{"class":180,"line":1054},73,[178,1056,1057],{"class":184},"\u003C\u002F",[178,1059,291],{"class":188},[178,1061,196],{"class":184},[178,1063,1065,1067,1069],{"class":180,"line":1064},74,[178,1066,1057],{"class":184},[178,1068,224],{"class":188},[178,1070,196],{"class":184},[178,1072,1074,1076,1079],{"class":180,"line":1073},75,[178,1075,202],{"class":184},[178,1077,1078],{"class":188},"body",[178,1080,196],{"class":184},[178,1082,1084,1087,1090,1093,1095,1098],{"class":180,"line":1083},76,[178,1085,1086],{"class":184},"  \u003C",[178,1088,1089],{"class":188},"div",[178,1091,1092],{"class":192}," class",[178,1094,210],{"class":184},[178,1096,1097],{"class":213},"\"pane\"",[178,1099,196],{"class":184},[178,1101,1103,1106,1109,1111,1113,1116,1119,1121,1124],{"class":180,"line":1102},77,[178,1104,1105],{"class":184},"    \u003C",[178,1107,1108],{"class":188},"aside",[178,1110,1092],{"class":192},[178,1112,210],{"class":184},[178,1114,1115],{"class":213},"\"pane__side\"",[178,1117,1118],{"class":192}," aria-labelledby",[178,1120,210],{"class":184},[178,1122,1123],{"class":213},"\"facets-title\"",[178,1125,196],{"class":184},[178,1127,1129,1132,1134,1136,1138,1141,1144,1146,1148,1151,1153],{"class":180,"line":1128},78,[178,1130,1131],{"class":184},"      \u003C",[178,1133,29],{"class":188},[178,1135,1092],{"class":192},[178,1137,210],{"class":184},[178,1139,1140],{"class":213},"\"side__title\"",[178,1142,1143],{"class":192}," id",[178,1145,210],{"class":184},[178,1147,1123],{"class":213},[178,1149,1150],{"class":184},">Filters\u003C\u002F",[178,1152,29],{"class":188},[178,1154,196],{"class":184},[178,1156,1158,1160,1163,1165,1167,1170],{"class":180,"line":1157},79,[178,1159,1131],{"class":184},[178,1161,1162],{"class":188},"ul",[178,1164,1092],{"class":192},[178,1166,210],{"class":184},[178,1168,1169],{"class":213},"\"side__facets\"",[178,1171,196],{"class":184},[178,1173,1175,1178,1181,1183,1185,1188,1191,1193],{"class":180,"line":1174},80,[178,1176,1177],{"class":184},"        \u003C",[178,1179,1180],{"class":188},"li",[178,1182,1092],{"class":192},[178,1184,210],{"class":184},[178,1186,1187],{"class":213},"\"facet\"",[178,1189,1190],{"class":184},">In stock\u003C\u002F",[178,1192,1180],{"class":188},[178,1194,196],{"class":184},[178,1196,1198,1200,1202,1204,1206,1208,1211,1213],{"class":180,"line":1197},81,[178,1199,1177],{"class":184},[178,1201,1180],{"class":188},[178,1203,1092],{"class":192},[178,1205,210],{"class":184},[178,1207,1187],{"class":213},[178,1209,1210],{"class":184},">Under $50\u003C\u002F",[178,1212,1180],{"class":188},[178,1214,196],{"class":184},[178,1216,1218,1220,1222,1224,1226,1228,1231,1233],{"class":180,"line":1217},82,[178,1219,1177],{"class":184},[178,1221,1180],{"class":188},[178,1223,1092],{"class":192},[178,1225,210],{"class":184},[178,1227,1187],{"class":213},[178,1229,1230],{"class":184},">Free returns\u003C\u002F",[178,1232,1180],{"class":188},[178,1234,196],{"class":184},[178,1236,1238,1241,1243],{"class":180,"line":1237},83,[178,1239,1240],{"class":184},"      \u003C\u002F",[178,1242,1162],{"class":188},[178,1244,196],{"class":184},[178,1246,1248,1251,1253],{"class":180,"line":1247},84,[178,1249,1250],{"class":184},"    \u003C\u002F",[178,1252,1108],{"class":188},[178,1254,196],{"class":184},[178,1256,1258,1260,1263,1265,1267,1270,1272,1274,1277],{"class":180,"line":1257},85,[178,1259,1105],{"class":184},[178,1261,1262],{"class":188},"article",[178,1264,1092],{"class":192},[178,1266,210],{"class":184},[178,1268,1269],{"class":213},"\"pane__main\"",[178,1271,1118],{"class":192},[178,1273,210],{"class":184},[178,1275,1276],{"class":213},"\"results-title\"",[178,1278,196],{"class":184},[178,1280,1282,1284,1286,1288,1290,1293,1295,1297,1299,1302,1304],{"class":180,"line":1281},86,[178,1283,1131],{"class":184},[178,1285,29],{"class":188},[178,1287,1092],{"class":192},[178,1289,210],{"class":184},[178,1291,1292],{"class":213},"\"main__title\"",[178,1294,1143],{"class":192},[178,1296,210],{"class":184},[178,1298,1276],{"class":213},[178,1300,1301],{"class":184},">Results\u003C\u002F",[178,1303,29],{"class":188},[178,1305,196],{"class":184},[178,1307,1309,1311,1313,1315,1317,1320],{"class":180,"line":1308},87,[178,1310,1131],{"class":184},[178,1312,14],{"class":188},[178,1314,1092],{"class":192},[178,1316,210],{"class":184},[178,1318,1319],{"class":213},"\"main__body\"",[178,1321,1322],{"class":184},">The sidebar never asks how wide the window is. It asks\n",[178,1324,1326],{"class":180,"line":1325},88,[178,1327,1328],{"class":184},"      how wide this pane is, so the same markup works full-bleed, in a modal, or\n",[178,1330,1332,1335,1337],{"class":180,"line":1331},89,[178,1333,1334],{"class":184},"      in a narrow column.\u003C\u002F",[178,1336,14],{"class":188},[178,1338,196],{"class":184},[178,1340,1342,1344,1346],{"class":180,"line":1341},90,[178,1343,1250],{"class":184},[178,1345,1262],{"class":188},[178,1347,196],{"class":184},[178,1349,1351,1354,1356],{"class":180,"line":1350},91,[178,1352,1353],{"class":184},"  \u003C\u002F",[178,1355,1089],{"class":188},[178,1357,196],{"class":184},[178,1359,1361,1363,1365],{"class":180,"line":1360},92,[178,1362,1057],{"class":184},[178,1364,1078],{"class":188},[178,1366,196],{"class":184},[178,1368,1370,1372,1374],{"class":180,"line":1369},93,[178,1371,1057],{"class":184},[178,1373,173],{"class":188},[178,1375,196],{"class":184},[14,1377,1378,1379,1382,1383,1386,1387,1386,1390,1393],{},"Note what is ",[586,1380,1381],{},"not"," in that stylesheet: no ",[37,1384,1385],{},"order",", no ",[37,1388,1389],{},"grid-row",[37,1391,1392],{},"grid-area"," names, no absolute positioning. The stacked state and the two-column state both follow document order, so there is nothing to keep in sync.",[155,1395],{},[29,1397,1399],{"id":1398},"key-technique-two-thresholds-one-axis","Key technique: two thresholds, one axis",[14,1401,1402,1403,1405],{},"The component has two independent decisions to make, and they are not the same decision. \"Can the sidebar and main sit beside each other?\" is a question about the pair — it depends on the sum of a usable sidebar and a usable main column, which is why 34rem and not some round viewport-flavoured number. \"Can the facet chips share a line?\" is a question about the sidebar's own content. Writing them as separate ",[37,1404,39],{}," rules with separate thresholds means each one changes when its own content demands it.",[14,1407,1408,1409,1412,1413,1416,1417,1421],{},"Both rules query inline size only. ",[37,1410,1411],{},"container-type: inline-size"," applies containment on the inline axis and leaves block size to flow naturally, so the panel can grow as tall as its content without the query re-evaluating. The alternative, ",[37,1414,1415],{},"container-type: size",", requires you to supply a block size from outside, and a text panel has no business having one; the distinction is worked through in ",[18,1418,1420],{"href":1419},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size\u002F","container-type: size vs inline-size",".",[14,1423,1424,1425,1428,1429,1432,1433,1436,1437,1439,1440,1443],{},"The shorthand ",[37,1426,1427],{},"container: pane \u002F inline-size"," sets ",[37,1430,1431],{},"container-name"," and ",[37,1434,1435],{},"container-type"," in one declaration. Naming is optional for a single container, but it becomes load-bearing the moment one of these panes ends up inside another — an unnamed ",[37,1438,39],{}," rule binds to the ",[586,1441,1442],{},"nearest"," ancestor container, which after nesting may not be the one you meant.",[155,1445],{},[29,1447,1449],{"id":1448},"source-order-versus-visual-order","Source order versus visual order",[14,1451,1452,1453,1456,1457,1460],{},"The tempting shortcut, once the strip exists, is to put the sidebar last in the HTML because \"on mobile the filters should come after the results\", then use ",[37,1454,1455],{},"order: -1"," or ",[37,1458,1459],{},"grid-row: 1"," to hoist it back above the main region on wide containers. This works visually and is a genuine accessibility defect.",[14,1462,1463,1465],{},[37,1464,1385],{}," and grid placement are visual-only. They change where boxes paint; they do not change the accessibility tree, and they do not change sequential focus navigation, which follows DOM order. So a sighted keyboard user Tabs from a control at the top of the screen straight into a control near the bottom, then back up. CSS Flexbox and CSS Grid both say as much in their layout specifications, and WCAG 2.2 Success Criterion 1.3.2 Meaningful Sequence and 2.4.3 Focus Order are the criteria you fail.",[14,1467,1468,1469,1473,1474,1477,1478,1421],{},"The rule that keeps you out of trouble: ",[1470,1471,1472],"strong",{},"pick the DOM order you want read aloud, then only ever change the axis, not the sequence."," Going from a column to a row keeps the first child first — it just moves it from \"above\" to \"left of\". Going from a column to a ",[586,1475,1476],{},"reversed"," row does not. If you genuinely need filters after results in the reading order and above them visually, that is a signal to change the markup — for example by making the sidebar a disclosure that sits early in the DOM and is collapsed by default in narrow containers, a pattern that composes well with ",[18,1479,1481],{"href":1480},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure\u002F","CSS-only accordions and disclosure",[14,1483,1484],{},"One legitimate exception: purely decorative or duplicated content, which is not in the reading order to begin with. Everything else, fix in the HTML.",[155,1486],{},[29,1488,1490],{"id":1489},"variation-a-sticky-sidebar-that-knows-when-to-give-up","Variation: a sticky sidebar that knows when to give up",[14,1492,1493,1494,1497,1498,1500],{},"On a wide container the sidebar is short and the main region is long, so ",[37,1495,1496],{},"position: sticky"," earns its place. On a narrow container it is a horizontal strip at the top of a scrolling region, where sticking it would eat the viewport. Because the sticky rule lives inside the same ",[37,1499,39],{}," block, it turns itself off automatically:",[169,1502,1506],{"className":1503,"code":1504,"language":1505,"meta":174,"style":174},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast","@container pane (min-width: 34rem) {\n  .pane__side {\n    position: sticky;\n    top: 1rem;\n    \u002F* Never taller than the viewport, so a long facet list scrolls\n       inside the sidebar rather than escaping it. *\u002F\n    max-block-size: calc(100dvh - 2rem);\n    overflow-y: auto;\n    \u002F* Keyboard users can scroll a focusable scroll container; without a\n       tabindex some engines will not let them reach it at all. *\u002F\n    scrollbar-gutter: stable;\n  }\n}\n","css",[37,1507,1508,1514,1520,1532,1545,1550,1555,1583,1595,1600,1605,1613,1617],{"__ignoreMap":174},[178,1509,1510,1512],{"class":180,"line":181},[178,1511,39],{"class":325},[178,1513,922],{"class":184},[178,1515,1516,1518],{"class":180,"line":199},[178,1517,407],{"class":192},[178,1519,419],{"class":184},[178,1521,1522,1525,1527,1530],{"class":180,"line":219},[178,1523,1524],{"class":192},"    position",[178,1526,308],{"class":184},[178,1528,1529],{"class":192},"sticky",[178,1531,440],{"class":184},[178,1533,1534,1537,1539,1541,1543],{"class":180,"line":229},[178,1535,1536],{"class":192},"    top",[178,1538,308],{"class":184},[178,1540,322],{"class":192},[178,1542,326],{"class":325},[178,1544,440],{"class":184},[178,1546,1547],{"class":180,"line":247},[178,1548,1549],{"class":369},"    \u002F* Never taller than the viewport, so a long facet list scrolls\n",[178,1551,1552],{"class":180,"line":272},[178,1553,1554],{"class":369},"       inside the sidebar rather than escaping it. *\u002F\n",[178,1556,1557,1560,1562,1565,1567,1570,1573,1576,1579,1581],{"class":180,"line":286},[178,1558,1559],{"class":192},"    max-block-size",[178,1561,308],{"class":184},[178,1563,1564],{"class":192},"calc",[178,1566,962],{"class":184},[178,1568,1569],{"class":192},"100",[178,1571,1572],{"class":325},"dvh",[178,1574,1575],{"class":325}," -",[178,1577,1578],{"class":192}," 2",[178,1580,326],{"class":325},[178,1582,974],{"class":184},[178,1584,1585,1588,1590,1593],{"class":180,"line":296},[178,1586,1587],{"class":192},"    overflow-y",[178,1589,308],{"class":184},[178,1591,1592],{"class":192},"auto",[178,1594,440],{"class":184},[178,1596,1597],{"class":180,"line":359},[178,1598,1599],{"class":369},"    \u002F* Keyboard users can scroll a focusable scroll container; without a\n",[178,1601,1602],{"class":180,"line":366},[178,1603,1604],{"class":369},"       tabindex some engines will not let them reach it at all. *\u002F\n",[178,1606,1607,1610],{"class":180,"line":373},[178,1608,1609],{"class":192},"    scrollbar-gutter",[178,1611,1612],{"class":184},": stable;\n",[178,1614,1615],{"class":180,"line":379},[178,1616,480],{"class":184},[178,1618,1619],{"class":180,"line":385},[178,1620,1621],{"class":184},"}\n",[14,1623,1624,1627,1628,1630,1631,1634],{},[37,1625,1626],{},"100dvh"," tracks the dynamic viewport, so the sidebar does not sit partly under a mobile browser's retracting toolbar. If you support engines without ",[37,1629,1572],{},", precede it with a ",[37,1632,1633],{},"100vh"," declaration as a same-property fallback.",[155,1636],{},[29,1638,1640],{"id":1639},"browser-support","Browser support",[14,1642,1643,1644,1646,1647,1649,1650,1652,1653,1432,1656,1659,1660,1662],{},"Size container queries — ",[37,1645,1435],{},", the ",[37,1648,393],{}," shorthand and ",[37,1651,39],{}," — shipped in Chrome 105, Edge 105, Safari 16.0 and Firefox 110, so they are safely assumed on current browsers. ",[37,1654,1655],{},"minmax()",[37,1657,1658],{},"grid-template-columns"," predate them by years and need no guard, and the dynamic viewport units (",[37,1661,1572],{},") used here are supported in every current engine.",[14,1664,1665,1666,1668,1669,1672,1673,1421],{},"Because the base styles are the single-column arrangement, an engine that ignores ",[37,1667,39],{}," entirely renders the stacked strip layout, which is correct rather than broken. If you need the two-column arrangement on such engines, add a viewport-based approximation guarded by ",[37,1670,1671],{},"@supports not (container-type: inline-size)","; the technique is covered in ",[18,1674,1676],{"href":1675},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports\u002F","feature detection with @supports",[155,1678],{},[29,1680,1682],{"id":1681},"faq","FAQ",[14,1684,1685,1688,1689,1691],{},[1470,1686,1687],{},"Why does my sidebar layout break when I move it into a modal?","\nBecause the breakpoint is a media query reading the viewport, which does not change when the component moves into a narrower box. Query the component's own wrapper with ",[37,1690,1411],{}," instead, and the modal copy reflows on its own measurements.",[14,1693,1694,1700,1701,1432,1703,1705],{},[1470,1695,1696,1697,1699],{},"Is it safe to reorder the sidebar and main content with the ",[37,1698,1385],{}," property?","\nOnly if the visual result still matches a sensible reading order. ",[37,1702,1385],{},[37,1704,1389],{}," move boxes visually but leave DOM order untouched, so screen reader and Tab order follow the source. Fix the source order rather than paper over it visually.",[14,1707,1708,1714,1715,1717,1718,1720,1721,1724,1725,1728],{},[1470,1709,1710,1711,1713],{},"Should the sidebar use a fixed ",[37,1712,326],{}," width or a fraction unit?","\nUse a fixed ",[37,1716,326],{}," or a ",[37,1719,1655],{}," track for the sidebar and ",[37,1722,1723],{},"minmax(0, 1fr)"," for the main column. A fraction unit on both makes the sidebar grow on very wide containers, and an unclamped ",[37,1726,1727],{},"1fr"," main column can be forced wider than the container by long unbreakable content.",[14,1730,1731,1734,1735,1737,1738,1741],{},[1470,1732,1733],{},"Can I put a container query breakpoint in a custom property?","\nNo. The width in an ",[37,1736,39],{}," prelude is not substituted from ",[37,1739,1740],{},"var()",", because at-rule preludes are evaluated before custom property substitution. Keep the threshold literal and store the matching track sizes in custom properties instead.",[29,1743,1745],{"id":1744},"related","Related",[1162,1747,1748,1755,1761,1768,1774],{},[1180,1749,1750,1754],{},[18,1751,1753],{"href":1752},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries\u002F","Responsive Forms with Container Queries"," — the same reflow discipline applied to labels and inputs.",[1180,1756,1757,1760],{},[18,1758,1759],{"href":46},"Container Query Data Tables"," — per-instance collapsing for tabular content.",[1180,1762,1763,1767],{},[18,1764,1766],{"href":1765},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fholy-grail-layout-with-grid\u002F","Holy Grail Layout with Grid"," — the page-level relative of this component.",[1180,1769,1770,1773],{},[18,1771,1772],{"href":20},"Responsive Component Patterns"," — the parent guide for component-level responsiveness.",[1180,1775,1776,1780],{},[18,1777,1779],{"href":1778},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fcreating-accessible-focus-indicators\u002F","Creating Accessible Focus Indicators"," — make the focus order you preserved actually visible.",[291,1782,1783],{},"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 .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":174,"searchDepth":199,"depth":199,"links":1785},[1786,1787,1788,1789,1790,1791,1792,1793],{"id":31,"depth":199,"text":32},{"id":159,"depth":199,"text":160},{"id":1398,"depth":199,"text":1399},{"id":1448,"depth":199,"text":1449},{"id":1489,"depth":199,"text":1490},{"id":1639,"depth":199,"text":1640},{"id":1681,"depth":199,"text":1682},{"id":1744,"depth":199,"text":1745},"Build a sidebar and main layout that reflows on its own container width, collapsing to a horizontal strip, without wrecking source order or the focus order.","md",{"pageTitle":1797,"datePublished":1798,"dateModified":1798,"faq":1799},"Container Query Sidebar Layouts","2026-07-20",[1800,1802,1805,1808],{"q":1687,"a":1801},"Because the breakpoint is a media query reading the viewport, which does not change when the component moves into a narrower box. Query the component's own wrapper with container-type inline-size instead, and the modal copy reflows on its own measurements.",{"q":1803,"a":1804},"Is it safe to reorder the sidebar and main content with the order property?","Only if the visual result still matches a sensible reading order. The order and grid-row properties move boxes visually but leave DOM order untouched, so screen reader and Tab order follow the source. Fix the source order rather than paper over it visually.",{"q":1806,"a":1807},"Should the sidebar use a fixed rem width or a fraction unit?","Use a fixed rem or a minmax track for the sidebar and minmax(0, 1fr) for the main column. A fraction unit on both makes the sidebar grow on very wide containers, and an unclamped 1fr main column can be forced wider than the container by long unbreakable content.",{"q":1733,"a":1809},"No. The width in an @container prelude is not substituted from var(), because at-rule preludes are evaluated before custom property substitution. Keep the threshold literal and store the matching track sizes in custom properties instead.","\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts",{"title":5,"description":1794},"mastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts\u002Findex","bOOXnqJhA1bNNdOzITW8mbuOlKf5rnKuRm7gmvZ_ykw",[1815,1818,1821,1824,1827,1830,1833,1836,1839,1842,1845,1848,1851,1854,1857,1860,1863,1866,1869,1872,1875,1878,1881,1884,1887,1890,1893,1896,1899,1902,1905,1908,1911,1914,1917,1920,1923,1926,1929,1932,1935,1938,1941,1944,1947,1950,1953,1955,1958,1961,1964,1967,1970,1973,1976,1979,1982,1985,1988,1991,1994,1997,2000,2003,2006,2009,2012,2015,2018,2021,2024,2026,2029,2032,2035,2038,2041,2044,2047,2050,2053,2054,2057,2060,2063,2066,2069,2072],{"path":1816,"title":1817},"\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":1819,"title":1820},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1822,"title":1823},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1825,"title":1826},"\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":1828,"title":1829},"\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":1831,"title":1832},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1834,"title":1835},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1837,"title":1838},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1840,"title":1841},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1843,"title":1844},"\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":1846,"title":1847},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":1849,"title":1850},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1852,"title":1853},"\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":1855,"title":1856},"\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":1858,"title":1859},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1861,"title":1862},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1864,"title":1865},"\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":1867,"title":1868},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1870,"title":1871},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1873,"title":1874},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1876,"title":1877},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1879,"title":1880},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1882,"title":1883},"\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":1885,"title":1886},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1888,"title":1889},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1891,"title":1892},"\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":1894,"title":1895},"\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":1897,"title":1898},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1900,"title":1901},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1903,"title":1904},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1906,"title":1907},"\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":1909,"title":1910},"\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":1912,"title":1913},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1915,"title":1916},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1918,"title":1919},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1921,"title":1922},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1924,"title":1925},"\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":1927,"title":1928},"\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":1930,"title":1931},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1933,"title":1934},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1936,"title":1937},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1939,"title":1940},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1942,"title":1943},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1945,"title":1946},"\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":1948,"title":1949},"\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":1951,"title":1952},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":342,"title":1954},"Modern CSS Layouts & Micro-Interactions",{"path":1956,"title":1957},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1959,"title":1960},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1962,"title":1963},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1965,"title":1966},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1968,"title":1969},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1971,"title":1972},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1974,"title":1975},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1977,"title":1978},"\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":1980,"title":1981},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1983,"title":1984},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1986,"title":1987},"\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":1989,"title":1990},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1992,"title":1993},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1995,"title":1996},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1998,"title":1999},"\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":2001,"title":2002},"\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":2004,"title":2005},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":2007,"title":2008},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":2010,"title":2011},"\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":2013,"title":2014},"\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":2016,"title":2017},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":2019,"title":2020},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":2022,"title":2023},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":2025,"title":26},"\u002Fmastering-container-queries-responsive-layouts",{"path":2027,"title":2028},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":2030,"title":2031},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":2033,"title":2034},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":2036,"title":2037},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":2039,"title":2040},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":2042,"title":2043},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":2045,"title":2046},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":2048,"title":2049},"\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":2051,"title":2052},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1810,"title":5},{"path":2055,"title":2056},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":2058,"title":2059},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":2061,"title":2062},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":2064,"title":2065},"\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":2067,"title":2068},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":2070,"title":2071},"\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":2073,"title":2074},"\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",1784566156645]