[{"data":1,"prerenderedAt":3726},["ShallowReactive",2],{"page-\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays":3,"content-all-pages":3465},{"id":4,"title":5,"body":6,"description":3445,"extension":3446,"meta":3447,"navigation":337,"path":3461,"seo":3462,"stem":3463,"__hash__":3464},"content\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Findex.md","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"type":7,"value":8,"toc":3423},"minimark",[9,13,28,34,75,204,207,212,215,290,292,296,299,384,389,399,402,434,436,440,712,729,731,735,740,743,747,835,844,850,855,858,1063,1086,1094,1100,1110,1217,1239,1251,1255,1261,1313,1325,1328,1395,1404,1413,1420,1422,1429,1465,1485,1499,1556,1573,1580,1595,1597,1601,1616,1900,2822,2859,2861,2865,2877,2897,2925,2939,2956,2958,2962,3032,3034,3038,3160,3184,3191,3193,3197,3317,3319,3323,3329,3341,3368,3379,3381,3385,3419],[10,11,5],"h1",{"id":12},"css-anchor-positioning-and-overlays-tethering-elements-without-javascript",[14,15,16,17,21,22,27],"p",{},"Every interface eventually grows something that has to float next to something else: a tooltip beside a help icon, a select menu under its button, a rich hover card beside an avatar, a validation bubble pointing at the field it complains about. For roughly fifteen years the only way to do that reliably was JavaScript — measure the trigger with ",[18,19,20],"code",{},"getBoundingClientRect()",", measure the viewport, do the arithmetic, write inline styles, then re-run all of it on every scroll and resize. CSS anchor positioning removes the arithmetic from the equation. This guide sits inside ",[23,24,26],"a",{"href":25},"\u002Fmastering-container-queries-responsive-layouts\u002F","Mastering Container Queries & Responsive Layouts",", and it covers the whole feature set: naming an anchor, binding to it, placing against it, and letting the browser retry placements when the first one does not fit.",[14,29,30],{},[31,32,33],"strong",{},"What this guide covers:",[35,36,37,48,58,68],"ul",{},[38,39,40,41,44,45],"li",{},"Declaring anchors with ",[18,42,43],{},"anchor-name"," and binding with ",[18,46,47],{},"position-anchor",[38,49,50,51,54,55],{},"Coarse placement with ",[18,52,53],{},"position-area"," and precise placement with ",[18,56,57],{},"anchor()",[38,59,60,61,64,65],{},"Automatic collision handling via ",[18,62,63],{},"position-try-fallbacks"," and ",[18,66,67],{},"@position-try",[38,69,70,71,74],{},"The top layer, the ",[18,72,73],{},"popover"," attribute, and why the two features need each other",[76,77,83,84,83,88,83,92,83,99,83,109,83,115,83,120,83,125,83,129,83,133,83,136,83,139,83,146,83,150,83,154,83,162,83,167,83,171,83,174,83,177,83,180,83,184,83,188,83,192,83,196,83,199],"svg",{"viewBox":78,"role":79,"ariaLabel":80,"xmlns":81,"style":82},"0 0 720 350","img","An anchor element exposes a name that an out-of-flow element binds to, then the browser retries fallback placements until one fits","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[85,86,87],"title",{},"Anchor binding and the fallback retry chain",[89,90,91],"desc",{},"The anchor element declares a name, the anchored element binds to it, and the browser walks a list of fallback placements until one fits the viewport.",[93,94,98],"text",{"x":95,"y":96,"style":97},"360","28","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","Name it, bind to it, then let the browser retry",[100,101],"rect",{"x":102,"y":103,"width":104,"height":105,"rx":106,"fill":107,"opacity":108},"30","56","290","92","10","#7aa2ff","0.18",[93,110,114],{"x":111,"y":112,"style":113},"175","86","text-anchor:middle;fill:currentColor;font:13px sans-serif","anchor element",[93,116,119],{"x":111,"y":117,"style":118},"112","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","anchor-name: --tip",[93,121,124],{"x":111,"y":122,"style":123},"133","text-anchor:middle;fill:currentColor;font:11px sans-serif;opacity:0.7","any element, in flow",[100,126],{"x":127,"y":103,"width":104,"height":105,"rx":106,"fill":107,"opacity":128},"400","0.28",[93,130,132],{"x":131,"y":112,"style":113},"545","anchored element",[93,134,135],{"x":131,"y":117,"style":118},"position-anchor: --tip",[93,137,138],{"x":131,"y":122,"style":123},"position: fixed or absolute",[140,141],"line",{"x1":142,"y1":143,"x2":127,"y2":143,"stroke":144,"strokeWidth":145},"320","102","currentColor","1.5",[93,147,149],{"x":95,"y":148,"style":123},"94","binds",[93,151,153],{"x":95,"y":152,"style":113},"192","fallback chain, tried in order",[100,155],{"x":102,"y":156,"width":157,"height":158,"rx":159,"fill":160,"stroke":144,"strokeWidth":145,"opacity":161},"212","200","60","8","none","0.55",[93,163,166],{"x":164,"y":165,"style":118},"130","238","block-start",[93,168,170],{"x":164,"y":169,"style":123},"258","overflows top",[100,172],{"x":173,"y":156,"width":157,"height":158,"rx":159,"fill":160,"stroke":144,"strokeWidth":145,"opacity":161},"260",[93,175,176],{"x":95,"y":165,"style":118},"flip-block",[93,178,179],{"x":95,"y":169,"style":123},"still overflows",[100,181],{"x":182,"y":156,"width":157,"height":158,"rx":159,"fill":107,"opacity":183},"490","0.3",[93,185,187],{"x":186,"y":165,"style":118},"590","flip-inline",[93,189,191],{"x":186,"y":169,"style":190},"text-anchor:middle;fill:currentColor;font:11px sans-serif;opacity:0.75","fits, painted",[140,193],{"x1":194,"y1":195,"x2":173,"y2":195,"stroke":144,"strokeWidth":145},"230","242",[140,197],{"x1":198,"y1":195,"x2":182,"y2":195,"stroke":144,"strokeWidth":145},"460",[93,200,203],{"x":95,"y":201,"style":202},"312","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.7","the browser recomputes the chain on scroll and resize, per frame",[205,206],"hr",{},[208,209,211],"h2",{"id":210},"prerequisites","Prerequisites",[14,213,214],{},"You will move faster through this guide if the following are already familiar:",[35,216,217,235,255,270],{},[38,218,219,222,223,226,227,230,231,234],{},[31,220,221],{},"Out-of-flow positioning."," Containing blocks, ",[18,224,225],{},"position: absolute"," versus ",[18,228,229],{},"position: fixed",", and how ",[18,232,233],{},"inset"," shorthand maps to physical offsets.",[38,236,237,240,241,243,244,247,248,64,251,254],{},[31,238,239],{},"Logical properties."," Anchor positioning speaks ",[18,242,166],{},", ",[18,245,246],{},"inline-end"," and friends, not ",[18,249,250],{},"top",[18,252,253],{},"right",". If logical axes are new, read them as \"block = the direction text lines stack, inline = the direction text flows.\"",[38,256,257,260,261,264,265,269],{},[31,258,259],{},"Feature detection."," The ",[18,262,263],{},"@supports"," at-rule and how to test a property\u002Fvalue pair; the guide on ",[23,266,268],{"href":267},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports\u002F","feature detection with @supports"," covers the syntax in depth.",[38,271,272,275,276,64,279,282,283,64,286,289],{},[31,273,274],{},"Discrete transitions."," ",[18,277,278],{},"@starting-style",[18,280,281],{},"transition-behavior: allow-discrete",", because overlays animate between ",[18,284,285],{},"display: none",[18,287,288],{},"display: block",".",[205,291],{},[208,293,295],{"id":294},"the-core-concept-a-named-reference-frame","The core concept: a named reference frame",[14,297,298],{},"The mechanism is a two-part handshake. One element publishes a name. Another element consumes that name and thereby acquires a second reference frame in addition to its containing block.",[300,301,306],"pre",{"className":302,"code":303,"language":304,"meta":305,"style":305},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F* 1. The anchor publishes a dashed-ident name. *\u002F\n.help-icon { anchor-name: --help; }\n\n\u002F* 2. The anchored element binds to that name and gains a reference frame. *\u002F\n.help-panel {\n  position: fixed;\n  position-anchor: --help;\n}\n","css","",[18,307,308,316,332,339,345,354,369,378],{"__ignoreMap":305},[309,310,312],"span",{"class":140,"line":311},1,[309,313,315],{"class":314},"sLBg1","\u002F* 1. The anchor publishes a dashed-ident name. *\u002F\n",[309,317,319,323,327,329],{"class":140,"line":318},2,[309,320,322],{"class":321},"s-5SL",".help-icon",[309,324,326],{"class":325},"suds8"," { ",[309,328,43],{"class":321},[309,330,331],{"class":325},": --help; }\n",[309,333,335],{"class":140,"line":334},3,[309,336,338],{"emptyLinePlaceholder":337},true,"\n",[309,340,342],{"class":140,"line":341},4,[309,343,344],{"class":314},"\u002F* 2. The anchored element binds to that name and gains a reference frame. *\u002F\n",[309,346,348,351],{"class":140,"line":347},5,[309,349,350],{"class":321},".help-panel",[309,352,353],{"class":325}," {\n",[309,355,357,360,363,366],{"class":140,"line":356},6,[309,358,359],{"class":321},"  position",[309,361,362],{"class":325},": ",[309,364,365],{"class":321},"fixed",[309,367,368],{"class":325},";\n",[309,370,372,375],{"class":140,"line":371},7,[309,373,374],{"class":321},"  position-anchor",[309,376,377],{"class":325},": --help;\n",[309,379,381],{"class":140,"line":380},8,[309,382,383],{"class":325},"}\n",[14,385,386,388],{},[18,387,43],{}," accepts a dashed identifier (or a comma-separated list of them, so one element can serve several distinct consumers). It creates no visual effect whatsoever; it is purely a declaration that \"this element's border box is addressable under this name.\"",[14,390,391,393,394,398],{},[18,392,47],{}," sets the ",[395,396,397],"em",{},"default anchor element"," for the element it is declared on. Once that link exists, the anchored element can be placed relative to the anchor's border box rather than relative to its containing block. Crucially, the containing block does not disappear — it still bounds scrolling and still supplies the fallback rectangle. Anchor positioning adds a coordinate system; it does not replace one.",[14,400,401],{},"Three constraints govern the whole feature and explain most of the confusion people hit:",[403,404,405,419,428],"ol",{},[38,406,407,275,410,412,413,415,416,418],{},[31,408,409],{},"The anchored element must be out of flow.",[18,411,225],{}," or ",[18,414,229],{},". A static or relative element with a perfectly valid ",[18,417,47],{}," simply lays out normally and ignores every anchor rule.",[38,420,421,424,425,289],{},[31,422,423],{},"The anchor must be visible to the anchored element."," The anchor has to be an element that the anchored element could, in principle, reach — in practice, it must precede the anchored element in tree order or be one of its ancestors, and it must not be inside a skipped subtree such as ",[18,426,427],{},"content-visibility: hidden",[38,429,430,433],{},[31,431,432],{},"Name collisions resolve to the last declaration in tree order."," Reusing one name across twenty list rows does not silently break — it silently picks the twentieth row. Scope names per instance when it matters.",[205,435],{},[208,437,439],{"id":438},"syntax-and-parameters","Syntax and parameters",[441,442,443,459],"table",{},[444,445,446],"thead",{},[447,448,449,453,456],"tr",{},[450,451,452],"th",{},"Token",[450,454,455],{},"Accepted values",[450,457,458],{},"Default",[460,461,462,485,501,544,581,617,647,675,697],"tbody",{},[447,463,464,469,481],{},[465,466,467],"td",{},[18,468,43],{},[465,470,471,473,474,243,477,480],{},[18,472,160],{},", or one or more dashed idents (",[18,475,476],{},"--menu",[18,478,479],{},"--menu, --alt",")",[465,482,483],{},[18,484,160],{},[447,486,487,491,497],{},[465,488,489],{},[18,490,47],{},[465,492,493,496],{},[18,494,495],{},"auto",", or a dashed ident naming an anchor",[465,498,499],{},[18,500,495],{},[447,502,503,507,540],{},[465,504,505],{},[18,506,53],{},[465,508,509,510,243,513,243,516,243,519,243,522,243,525,528,529,531,532,531,535,531,538],{},"one or two keywords from the block\u002Finline row-column grid: ",[18,511,512],{},"start",[18,514,515],{},"center",[18,517,518],{},"end",[18,520,521],{},"span-start",[18,523,524],{},"span-end",[18,526,527],{},"span-all",", plus physical aliases ",[18,530,250],{},"\u002F",[18,533,534],{},"bottom",[18,536,537],{},"left",[18,539,253],{},[465,541,542],{},[18,543,160],{},[447,545,546,550,578],{},[465,547,548],{},[18,549,57],{},[465,551,552,412,555,558,559,243,561,243,563,243,566,243,569,243,571,243,574,577],{},[18,553,554],{},"anchor(\u003Cside>)",[18,556,557],{},"anchor(--name \u003Cside>, \u003Cfallback>)","; sides are ",[18,560,512],{},[18,562,518],{},[18,564,565],{},"self-start",[18,567,568],{},"self-end",[18,570,515],{},[18,572,573],{},"inside",[18,575,576],{},"outside",", or a percentage",[465,579,580],{},"—",[447,582,583,588,615],{},[465,584,585],{},[18,586,587],{},"anchor-size()",[465,589,590,412,593,596,597,243,600,243,603,243,606,243,609,243,612],{},[18,591,592],{},"anchor-size(\u003Caxis>)",[18,594,595],{},"anchor-size(--name \u003Caxis>)","; axes are ",[18,598,599],{},"width",[18,601,602],{},"height",[18,604,605],{},"block",[18,607,608],{},"inline",[18,610,611],{},"self-block",[18,613,614],{},"self-inline",[465,616,580],{},[447,618,619,623,643],{},[465,620,621],{},[18,622,63],{},[465,624,625,627,628,243,630,243,632,635,636,639,640,642],{},[18,626,160],{},", or a list of ",[18,629,176],{},[18,631,187],{},[18,633,634],{},"flip-start",", a ",[18,637,638],{},"position-area()"," value, or a ",[18,641,67],{}," rule name",[465,644,645],{},[18,646,160],{},[447,648,649,654,671],{},[465,650,651],{},[18,652,653],{},"position-try-order",[465,655,656,243,659,243,662,243,665,243,668],{},[18,657,658],{},"normal",[18,660,661],{},"most-width",[18,663,664],{},"most-height",[18,666,667],{},"most-block-size",[18,669,670],{},"most-inline-size",[465,672,673],{},[18,674,658],{},[447,676,677,682,693],{},[465,678,679],{},[18,680,681],{},"position-visibility",[465,683,684,243,687,243,690],{},[18,685,686],{},"always",[18,688,689],{},"anchors-visible",[18,691,692],{},"no-overflow",[465,694,695],{},[18,696,686],{},[447,698,699,704,710],{},[465,700,701],{},[18,702,703],{},"@position-try --name { … }",[465,705,706,707,709],{},"a block of inset, margin, ",[18,708,53],{},", sizing and alignment declarations",[465,711,580],{},[14,713,714,715,718,719,722,723,725,726,728],{},"Two shorthands are worth memorising. ",[18,716,717],{},"position-try"," combines order and fallbacks in one declaration. And ",[18,720,721],{},"inset-area"," was the property's name during the early Chrome ship; it was renamed to ",[18,724,53],{}," before the feature stabilised, so treat any tutorial mentioning ",[18,727,721],{}," as pre-2025 material.",[205,730],{},[208,732,734],{"id":733},"step-by-step-implementation","Step-by-step implementation",[736,737,739],"h3",{"id":738},"step-1-tether-without-doing-any-arithmetic","Step 1 — Tether without doing any arithmetic",[14,741,742],{},"Start with the simplest possible pairing: a panel that hangs below a button. The demo below is the whole feature in miniature — nothing measures anything.",[744,745],"live-demo",{"name":746},"anchor-basic-tether",[300,748,750],{"className":302,"code":749,"language":304,"meta":305,"style":305},".tether-btn {\n  anchor-name: --account;\n}\n\n.tether-panel {\n  position: fixed;\n  position-anchor: --account;\n  position-area: block-end center;\n  margin-block-start: 0.5rem;\n}\n",[18,751,752,759,767,771,775,782,792,798,813,830],{"__ignoreMap":305},[309,753,754,757],{"class":140,"line":311},[309,755,756],{"class":321},".tether-btn",[309,758,353],{"class":325},[309,760,761,764],{"class":140,"line":318},[309,762,763],{"class":321},"  anchor-name",[309,765,766],{"class":325},": --account;\n",[309,768,769],{"class":140,"line":334},[309,770,383],{"class":325},[309,772,773],{"class":140,"line":341},[309,774,338],{"emptyLinePlaceholder":337},[309,776,777,780],{"class":140,"line":347},[309,778,779],{"class":321},".tether-panel",[309,781,353],{"class":325},[309,783,784,786,788,790],{"class":140,"line":356},[309,785,359],{"class":321},[309,787,362],{"class":325},[309,789,365],{"class":321},[309,791,368],{"class":325},[309,793,794,796],{"class":140,"line":371},[309,795,374],{"class":321},[309,797,766],{"class":325},[309,799,800,803,805,808,811],{"class":140,"line":380},[309,801,802],{"class":321},"  position-area",[309,804,362],{"class":325},[309,806,807],{"class":321},"block-end",[309,809,810],{"class":321}," center",[309,812,368],{"class":325},[309,814,816,819,821,824,828],{"class":140,"line":815},9,[309,817,818],{"class":321},"  margin-block-start",[309,820,362],{"class":325},[309,822,823],{"class":321},"0.5",[309,825,827],{"class":826},"sHUrx","rem",[309,829,368],{"class":325},[309,831,833],{"class":140,"line":832},10,[309,834,383],{"class":325},[14,836,837,839,840,843],{},[18,838,229],{}," here is deliberate rather than incidental. Because the anchored element takes its geometry from the anchor rather than from an ancestor, a fixed element is no longer stuck to the viewport — the browser tracks the anchor as it scrolls and moves the panel with it. This is the single biggest ergonomic win: you get scroll-following behaviour without a scroll listener, and because the panel has no positioned ancestor, no ancestor's ",[18,841,842],{},"overflow: hidden"," can clip it.",[736,845,847,848],{"id":846},"step-2-place-coarsely-with-position-area","Step 2 — Place coarsely with ",[18,849,53],{},[14,851,852,854],{},[18,853,53],{}," treats the anchor as the centre cell of a three-by-three grid and lets you name the cell (or span of cells) the anchored element should occupy. One keyword sets both axes symmetrically; two keywords set block then inline.",[744,856],{"name":857},"anchor-position-area-map",[300,859,861],{"className":302,"code":860,"language":304,"meta":305,"style":305},".pa-anchor { anchor-name: --hub; }\n\n.pa {\n  position: fixed;\n  position-anchor: --hub;\n  margin: 0.3rem;\n}\n\n.pa--ts { position-area: block-start span-inline-start; }\n.pa--tc { position-area: block-start center; }\n.pa--te { position-area: block-start span-inline-end; }\n.pa--ms { position-area: center inline-start; }\n.pa--me { position-area: center inline-end; }\n.pa--bs { position-area: block-end span-inline-start; }\n.pa--bc { position-area: block-end center; }\n.pa--be { position-area: block-end span-inline-end; }\n",[18,862,863,875,879,886,896,903,916,920,924,940,958,975,994,1013,1029,1047],{"__ignoreMap":305},[309,864,865,868,870,872],{"class":140,"line":311},[309,866,867],{"class":321},".pa-anchor",[309,869,326],{"class":325},[309,871,43],{"class":321},[309,873,874],{"class":325},": --hub; }\n",[309,876,877],{"class":140,"line":318},[309,878,338],{"emptyLinePlaceholder":337},[309,880,881,884],{"class":140,"line":334},[309,882,883],{"class":321},".pa",[309,885,353],{"class":325},[309,887,888,890,892,894],{"class":140,"line":341},[309,889,359],{"class":321},[309,891,362],{"class":325},[309,893,365],{"class":321},[309,895,368],{"class":325},[309,897,898,900],{"class":140,"line":347},[309,899,374],{"class":321},[309,901,902],{"class":325},": --hub;\n",[309,904,905,908,910,912,914],{"class":140,"line":356},[309,906,907],{"class":321},"  margin",[309,909,362],{"class":325},[309,911,183],{"class":321},[309,913,827],{"class":826},[309,915,368],{"class":325},[309,917,918],{"class":140,"line":371},[309,919,383],{"class":325},[309,921,922],{"class":140,"line":380},[309,923,338],{"emptyLinePlaceholder":337},[309,925,926,929,931,933,935,937],{"class":140,"line":815},[309,927,928],{"class":321},".pa--ts",[309,930,326],{"class":325},[309,932,53],{"class":321},[309,934,362],{"class":325},[309,936,166],{"class":321},[309,938,939],{"class":325}," span-inline-start; }\n",[309,941,942,945,947,949,951,953,955],{"class":140,"line":832},[309,943,944],{"class":321},".pa--tc",[309,946,326],{"class":325},[309,948,53],{"class":321},[309,950,362],{"class":325},[309,952,166],{"class":321},[309,954,810],{"class":321},[309,956,957],{"class":325},"; }\n",[309,959,961,964,966,968,970,972],{"class":140,"line":960},11,[309,962,963],{"class":321},".pa--te",[309,965,326],{"class":325},[309,967,53],{"class":321},[309,969,362],{"class":325},[309,971,166],{"class":321},[309,973,974],{"class":325}," span-inline-end; }\n",[309,976,978,981,983,985,987,989,992],{"class":140,"line":977},12,[309,979,980],{"class":321},".pa--ms",[309,982,326],{"class":325},[309,984,53],{"class":321},[309,986,362],{"class":325},[309,988,515],{"class":321},[309,990,991],{"class":321}," inline-start",[309,993,957],{"class":325},[309,995,997,1000,1002,1004,1006,1008,1011],{"class":140,"line":996},13,[309,998,999],{"class":321},".pa--me",[309,1001,326],{"class":325},[309,1003,53],{"class":321},[309,1005,362],{"class":325},[309,1007,515],{"class":321},[309,1009,1010],{"class":321}," inline-end",[309,1012,957],{"class":325},[309,1014,1016,1019,1021,1023,1025,1027],{"class":140,"line":1015},14,[309,1017,1018],{"class":321},".pa--bs",[309,1020,326],{"class":325},[309,1022,53],{"class":321},[309,1024,362],{"class":325},[309,1026,807],{"class":321},[309,1028,939],{"class":325},[309,1030,1032,1035,1037,1039,1041,1043,1045],{"class":140,"line":1031},15,[309,1033,1034],{"class":321},".pa--bc",[309,1036,326],{"class":325},[309,1038,53],{"class":321},[309,1040,362],{"class":325},[309,1042,807],{"class":321},[309,1044,810],{"class":321},[309,1046,957],{"class":325},[309,1048,1050,1053,1055,1057,1059,1061],{"class":140,"line":1049},16,[309,1051,1052],{"class":321},".pa--be",[309,1054,326],{"class":325},[309,1056,53],{"class":321},[309,1058,362],{"class":325},[309,1060,807],{"class":321},[309,1062,974],{"class":325},[14,1064,1065,1066,1069,1070,1073,1074,1077,1078,1081,1082,1085],{},"The ",[18,1067,1068],{},"span-*"," keywords are what make this practical for real menus. ",[18,1071,1072],{},"block-end span-inline-end"," means \"below the anchor, occupying the anchor's own inline column ",[395,1075,1076],{},"plus"," the column after it\" — the classic dropdown that is left-aligned with its button and grows rightwards, which is otherwise a fiddly ",[18,1079,1080],{},"left: 0"," plus ",[18,1083,1084],{},"min-width"," dance.",[14,1087,1088,1090,1091,289],{},[18,1089,53],{}," also does alignment for free. Placing an element in a cell sets its self-alignment to fill that cell sensibly, which is why the panels above are centred without a single ",[18,1092,1093],{},"translate: -50%",[736,1095,1097,1098],{"id":1096},"step-3-place-precisely-with-anchor","Step 3 — Place precisely with ",[18,1099,57],{},[14,1101,1102,1103,1105,1106,1109],{},"When a grid cell is too blunt, ",[18,1104,57],{}," returns a length: the position of one edge of the anchor, usable anywhere a ",[18,1107,1108],{},"\u003Clength-percentage>"," is valid.",[300,1111,1113],{"className":302,"code":1112,"language":304,"meta":305,"style":305},".callout {\n  position: fixed;\n  position-anchor: --field;\n\n  \u002F* Top edge of the callout sits on the bottom edge of the anchor. *\u002F\n  top: anchor(bottom);\n  \u002F* Left edges align. *\u002F\n  left: anchor(left);\n  \u002F* Never wider than the anchor. *\u002F\n  max-width: anchor-size(width);\n  \u002F* Never narrower than half of it. *\u002F\n  min-width: calc(anchor-size(width) \u002F 2);\n}\n",[18,1114,1115,1122,1132,1139,1143,1148,1161,1166,1177,1182,1190,1195,1213],{"__ignoreMap":305},[309,1116,1117,1120],{"class":140,"line":311},[309,1118,1119],{"class":321},".callout",[309,1121,353],{"class":325},[309,1123,1124,1126,1128,1130],{"class":140,"line":318},[309,1125,359],{"class":321},[309,1127,362],{"class":325},[309,1129,365],{"class":321},[309,1131,368],{"class":325},[309,1133,1134,1136],{"class":140,"line":334},[309,1135,374],{"class":321},[309,1137,1138],{"class":325},": --field;\n",[309,1140,1141],{"class":140,"line":341},[309,1142,338],{"emptyLinePlaceholder":337},[309,1144,1145],{"class":140,"line":347},[309,1146,1147],{"class":314},"  \u002F* Top edge of the callout sits on the bottom edge of the anchor. *\u002F\n",[309,1149,1150,1153,1156,1158],{"class":140,"line":356},[309,1151,1152],{"class":321},"  top",[309,1154,1155],{"class":325},": anchor(",[309,1157,534],{"class":321},[309,1159,1160],{"class":325},");\n",[309,1162,1163],{"class":140,"line":371},[309,1164,1165],{"class":314},"  \u002F* Left edges align. *\u002F\n",[309,1167,1168,1171,1173,1175],{"class":140,"line":380},[309,1169,1170],{"class":321},"  left",[309,1172,1155],{"class":325},[309,1174,537],{"class":321},[309,1176,1160],{"class":325},[309,1178,1179],{"class":140,"line":815},[309,1180,1181],{"class":314},"  \u002F* Never wider than the anchor. *\u002F\n",[309,1183,1184,1187],{"class":140,"line":832},[309,1185,1186],{"class":321},"  max-width",[309,1188,1189],{"class":325},": anchor-size(width);\n",[309,1191,1192],{"class":140,"line":960},[309,1193,1194],{"class":314},"  \u002F* Never narrower than half of it. *\u002F\n",[309,1196,1197,1200,1202,1205,1208,1211],{"class":140,"line":977},[309,1198,1199],{"class":321},"  min-width",[309,1201,362],{"class":325},[309,1203,1204],{"class":321},"calc",[309,1206,1207],{"class":325},"(anchor-size(width) \u002F ",[309,1209,1210],{"class":321},"2",[309,1212,1160],{"class":325},[309,1214,1215],{"class":140,"line":996},[309,1216,383],{"class":325},[14,1218,1219,1220,1222,1223,243,1226,243,1229,64,1232,1235,1236,289],{},"Because ",[18,1221,57],{}," resolves to a plain length, it composes with ",[18,1224,1225],{},"calc()",[18,1227,1228],{},"min()",[18,1230,1231],{},"max()",[18,1233,1234],{},"clamp()",". That is how you build things a placement grid cannot express: a caret that tracks the anchor's horizontal centre while the bubble itself is clamped to the viewport, or a mega-menu whose height is ",[18,1237,1238],{},"calc(100vh - anchor(bottom) - 1rem)",[14,1240,1241,1243,1244,1247,1248,1250],{},[18,1242,57],{}," accepts a fallback as its final argument — ",[18,1245,1246],{},"anchor(--maybe bottom, 100%)"," — which is what keeps a rule from being dropped as invalid at computed-value time when the named anchor is missing. Without a fallback, an unresolvable ",[18,1249,57],{}," makes the whole declaration behave as if the element had no such inset.",[736,1252,1254],{"id":1253},"step-4-let-the-browser-handle-collisions","Step 4 — Let the browser handle collisions",[14,1256,1257,1258,1260],{},"A tethered element that renders half off-screen is worse than no tethering at all. ",[18,1259,63],{}," gives the browser an ordered list of alternative placements; it lays the element out with the primary placement, checks whether it overflows its inset-modified containing block, and if so re-runs layout with the next candidate until one fits or the list is exhausted.",[300,1262,1264],{"className":302,"code":1263,"language":304,"meta":305,"style":305},".menu {\n  position: fixed;\n  position-anchor: --menu-btn;\n  position-area: block-end span-inline-end;\n  position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;\n}\n",[18,1265,1266,1273,1283,1290,1301,1309],{"__ignoreMap":305},[309,1267,1268,1271],{"class":140,"line":311},[309,1269,1270],{"class":321},".menu",[309,1272,353],{"class":325},[309,1274,1275,1277,1279,1281],{"class":140,"line":318},[309,1276,359],{"class":321},[309,1278,362],{"class":325},[309,1280,365],{"class":321},[309,1282,368],{"class":325},[309,1284,1285,1287],{"class":140,"line":334},[309,1286,374],{"class":321},[309,1288,1289],{"class":325},": --menu-btn;\n",[309,1291,1292,1294,1296,1298],{"class":140,"line":341},[309,1293,802],{"class":321},[309,1295,362],{"class":325},[309,1297,807],{"class":321},[309,1299,1300],{"class":325}," span-inline-end;\n",[309,1302,1303,1306],{"class":140,"line":347},[309,1304,1305],{"class":321},"  position-try-fallbacks",[309,1307,1308],{"class":325},": flip-block, flip-inline, flip-block flip-inline;\n",[309,1310,1311],{"class":140,"line":356},[309,1312,383],{"class":325},[14,1314,1315,1316,1318,1319,1321,1322,1324],{},"The three built-in keywords mirror the placement across an axis: ",[18,1317,176],{}," swaps block-start for block-end, ",[18,1320,187],{}," swaps the inline sides, and ",[18,1323,634],{}," transposes the two axes entirely (turning a below-placement into a beside-placement). Combining two keywords in one candidate, as in the last entry above, produces a diagonal flip.",[14,1326,1327],{},"For anything the keywords cannot express, declare a named candidate:",[300,1329,1331],{"className":302,"code":1330,"language":304,"meta":305,"style":305},"@position-try --menu-stacked {\n  position-area: block-end span-all;\n  width: anchor-size(width);\n  margin: 0.25rem 0 0;\n}\n\n.menu {\n  position-try-fallbacks: flip-block, --menu-stacked;\n}\n",[18,1332,1333,1340,1354,1359,1370,1374,1378,1384,1391],{"__ignoreMap":305},[309,1334,1335,1337],{"class":140,"line":311},[309,1336,67],{"class":826},[309,1338,1339],{"class":325}," --menu-stacked {\n",[309,1341,1342,1345,1347,1349,1352],{"class":140,"line":318},[309,1343,802],{"class":1344},"sne4z",[309,1346,362],{"class":325},[309,1348,807],{"class":1344},[309,1350,1351],{"class":1344}," span-all",[309,1353,368],{"class":325},[309,1355,1356],{"class":140,"line":334},[309,1357,1358],{"class":325},"  width: anchor-size(width);\n",[309,1360,1361,1364,1367],{"class":140,"line":341},[309,1362,1363],{"class":325},"  margin: 0",[309,1365,1366],{"class":321},".25rem",[309,1368,1369],{"class":325}," 0 0;\n",[309,1371,1372],{"class":140,"line":347},[309,1373,383],{"class":325},[309,1375,1376],{"class":140,"line":356},[309,1377,338],{"emptyLinePlaceholder":337},[309,1379,1380,1382],{"class":140,"line":371},[309,1381,1270],{"class":321},[309,1383,353],{"class":325},[309,1385,1386,1388],{"class":140,"line":380},[309,1387,1305],{"class":321},[309,1389,1390],{"class":325},": flip-block, --menu-stacked;\n",[309,1392,1393],{"class":140,"line":815},[309,1394,383],{"class":325},[14,1396,1397,1398,1400,1401,1403],{},"A ",[18,1399,67],{}," block may only contain inset properties, margin, sizing, self-alignment and ",[18,1402,53],{},". Anything else — colours, borders, transitions — is ignored, which keeps fallbacks cheap: the browser is re-running layout for the candidate, not restyling the subtree.",[14,1405,1406,1408,1409,1412],{},[18,1407,653],{}," changes the selection strategy from \"first that fits\" to \"the one that yields the most space.\" ",[18,1410,1411],{},"position-try-order: most-block-size"," is the right choice for a long dropdown that should open in whichever direction gives it the most room, even when both directions technically fit.",[14,1414,1415,1416,1419],{},"Finally, ",[18,1417,1418],{},"position-visibility: anchors-visible"," hides the anchored element outright when its anchor scrolls out of view. Without it, a tooltip stays pinned at the edge of the scrollport pointing at nothing.",[205,1421],{},[208,1423,1425,1426,1428],{"id":1424},"the-top-layer-and-where-popover-comes-in","The top layer, and where ",[18,1427,73],{}," comes in",[14,1430,1431,1432,1435,1436,1439,1440,1442,1443,412,1446,1449,1450,1452,1453,1456,1457,1460,1461,1464],{},"Anchor positioning solves ",[395,1433,1434],{},"where",". It says nothing about ",[395,1437,1438],{},"stacking",", and stacking is the other half of every overlay bug ever filed. A dropdown inside a card with ",[18,1441,842],{}," gets clipped. A modal inside an ancestor with ",[18,1444,1445],{},"transform",[18,1447,1448],{},"filter"," finds that its ",[18,1451,229],{}," is now relative to that ancestor rather than the viewport. A tooltip inside a ",[18,1454,1455],{},"z-index: 1"," section can never rise above a ",[18,1458,1459],{},"z-index: 2"," sibling section, no matter how large its own ",[18,1462,1463],{},"z-index"," grows, because stacking contexts nest.",[14,1466,1065,1467,1470,1471,243,1474,243,1476,64,1478,1481,1482,1484],{},[31,1468,1469],{},"top layer"," is the browser's escape hatch. It is a viewport-sized rendering layer that sits above the entire document, outside every stacking context, immune to ancestor ",[18,1472,1473],{},"overflow",[18,1475,1445],{},[18,1477,1448],{},[18,1479,1480],{},"contain",". Elements in it paint in the order they were promoted, so the last one promoted is on top — ",[18,1483,1463],{}," between top-layer elements is irrelevant.",[14,1486,1487,1488,1491,1492,1495,1496,1498],{},"Only three things put an element in the top layer: a fullscreen request, ",[18,1489,1490],{},"\u003Cdialog>"," opened with ",[18,1493,1494],{},"showModal()",", and an element with the ",[18,1497,73],{}," attribute being shown. The first two need JavaScript. The third does not:",[300,1500,1504],{"className":1501,"code":1502,"language":1503,"meta":305,"style":305},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cbutton popovertarget=\"filters\">Filters\u003C\u002Fbutton>\n\u003Cdiv id=\"filters\" popover>…\u003C\u002Fdiv>\n","html",[18,1505,1506,1532],{"__ignoreMap":305},[309,1507,1508,1511,1514,1517,1520,1524,1527,1529],{"class":140,"line":311},[309,1509,1510],{"class":325},"\u003C",[309,1512,1513],{"class":1344},"button",[309,1515,1516],{"class":321}," popovertarget",[309,1518,1519],{"class":325},"=",[309,1521,1523],{"class":1522},"sT6z2","\"filters\"",[309,1525,1526],{"class":325},">Filters\u003C\u002F",[309,1528,1513],{"class":1344},[309,1530,1531],{"class":325},">\n",[309,1533,1534,1536,1539,1542,1544,1546,1549,1552,1554],{"class":140,"line":318},[309,1535,1510],{"class":325},[309,1537,1538],{"class":1344},"div",[309,1540,1541],{"class":321}," id",[309,1543,1519],{"class":325},[309,1545,1523],{"class":1522},[309,1547,1548],{"class":321}," popover",[309,1550,1551],{"class":325},">…\u003C\u002F",[309,1553,1538],{"class":1344},[309,1555,1531],{"class":325},[14,1557,1558,1559,1563,1564,1568,1569,1572],{},"That markup gives you a panel that opens on click, closes on ",[1560,1561,1562],"kbd",{},"Escape",", closes when you click outside it (light dismiss), sits in the top layer, and is exposed to assistive technology with an implicit relationship between button and panel — all from two attributes and no script. The ",[23,1565,1567],{"href":1566},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling\u002F","popover attribute and CSS styling"," page takes that markup apart in detail, including ",[18,1570,1571],{},"::backdrop"," and entry\u002Fexit animation.",[14,1574,1575,1576,1579],{},"The reason these two features arrived together is that each creates a problem the other solves. A top-layer element has no positioned ancestor by definition, so before anchor positioning the only way to place a popover next to its trigger was — again — JavaScript measurement. And an anchored element that is ",[395,1577,1578],{},"not"," in the top layer remains vulnerable to every clipping and stacking hazard listed above. Used together you get an overlay that is both correctly stacked and correctly placed with no script at all.",[14,1581,1582,1583,1586,1587,1590,1591,1594],{},"One convenience worth knowing: an element opened via ",[18,1584,1585],{},"popovertarget"," gets an ",[31,1588,1589],{},"implicit anchor reference",", so ",[18,1592,1593],{},"position-anchor: auto"," resolves to the invoking button without either element declaring a name. Explicit names are still preferable for anything reused, because implicit anchoring only works through the popover invoker relationship.",[205,1596],{},[208,1598,1600],{"id":1599},"annotated-production-example-a-filter-menu","Annotated production example: a filter menu",[14,1602,1603,1604,1606,1607,1609,1610,1612,1613,1615],{},"The following is a complete, copy-paste dropdown that combines everything above: top-layer stacking from ",[18,1605,73],{},", placement from ",[18,1608,53],{},", collision handling from ",[18,1611,63],{},", width matching from ",[18,1614,587],{},", and animated entry using discrete transitions.",[300,1617,1619],{"className":1501,"code":1618,"language":1503,"meta":305,"style":305},"\u003Cdiv class=\"toolbar\">\n  \u003Cbutton class=\"filter-btn\" popovertarget=\"filter-menu\">\n    Filters\n    \u003Cspan aria-hidden=\"true\">▾\u003C\u002Fspan>\n  \u003C\u002Fbutton>\n\n  \u003Cdiv id=\"filter-menu\" popover class=\"filter-menu\">\n    \u003Cp class=\"filter-menu__label\" id=\"filter-label\">Show items that are\u003C\u002Fp>\n    \u003Cul class=\"filter-menu__list\" aria-labelledby=\"filter-label\">\n      \u003Cli>\u003Clabel>\u003Cinput type=\"checkbox\" checked> In stock\u003C\u002Flabel>\u003C\u002Fli>\n      \u003Cli>\u003Clabel>\u003Cinput type=\"checkbox\"> On sale\u003C\u002Flabel>\u003C\u002Fli>\n      \u003Cli>\u003Clabel>\u003Cinput type=\"checkbox\"> New arrivals\u003C\u002Flabel>\u003C\u002Fli>\n    \u003C\u002Ful>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n",[18,1620,1621,1637,1660,1665,1687,1696,1700,1722,1749,1771,1812,1843,1874,1883,1891],{"__ignoreMap":305},[309,1622,1623,1625,1627,1630,1632,1635],{"class":140,"line":311},[309,1624,1510],{"class":325},[309,1626,1538],{"class":1344},[309,1628,1629],{"class":321}," class",[309,1631,1519],{"class":325},[309,1633,1634],{"class":1522},"\"toolbar\"",[309,1636,1531],{"class":325},[309,1638,1639,1642,1644,1646,1648,1651,1653,1655,1658],{"class":140,"line":318},[309,1640,1641],{"class":325},"  \u003C",[309,1643,1513],{"class":1344},[309,1645,1629],{"class":321},[309,1647,1519],{"class":325},[309,1649,1650],{"class":1522},"\"filter-btn\"",[309,1652,1516],{"class":321},[309,1654,1519],{"class":325},[309,1656,1657],{"class":1522},"\"filter-menu\"",[309,1659,1531],{"class":325},[309,1661,1662],{"class":140,"line":334},[309,1663,1664],{"class":325},"    Filters\n",[309,1666,1667,1670,1672,1675,1677,1680,1683,1685],{"class":140,"line":341},[309,1668,1669],{"class":325},"    \u003C",[309,1671,309],{"class":1344},[309,1673,1674],{"class":321}," aria-hidden",[309,1676,1519],{"class":325},[309,1678,1679],{"class":1522},"\"true\"",[309,1681,1682],{"class":325},">▾\u003C\u002F",[309,1684,309],{"class":1344},[309,1686,1531],{"class":325},[309,1688,1689,1692,1694],{"class":140,"line":347},[309,1690,1691],{"class":325},"  \u003C\u002F",[309,1693,1513],{"class":1344},[309,1695,1531],{"class":325},[309,1697,1698],{"class":140,"line":356},[309,1699,338],{"emptyLinePlaceholder":337},[309,1701,1702,1704,1706,1708,1710,1712,1714,1716,1718,1720],{"class":140,"line":371},[309,1703,1641],{"class":325},[309,1705,1538],{"class":1344},[309,1707,1541],{"class":321},[309,1709,1519],{"class":325},[309,1711,1657],{"class":1522},[309,1713,1548],{"class":321},[309,1715,1629],{"class":321},[309,1717,1519],{"class":325},[309,1719,1657],{"class":1522},[309,1721,1531],{"class":325},[309,1723,1724,1726,1728,1730,1732,1735,1737,1739,1742,1745,1747],{"class":140,"line":380},[309,1725,1669],{"class":325},[309,1727,14],{"class":1344},[309,1729,1629],{"class":321},[309,1731,1519],{"class":325},[309,1733,1734],{"class":1522},"\"filter-menu__label\"",[309,1736,1541],{"class":321},[309,1738,1519],{"class":325},[309,1740,1741],{"class":1522},"\"filter-label\"",[309,1743,1744],{"class":325},">Show items that are\u003C\u002F",[309,1746,14],{"class":1344},[309,1748,1531],{"class":325},[309,1750,1751,1753,1755,1757,1759,1762,1765,1767,1769],{"class":140,"line":815},[309,1752,1669],{"class":325},[309,1754,35],{"class":1344},[309,1756,1629],{"class":321},[309,1758,1519],{"class":325},[309,1760,1761],{"class":1522},"\"filter-menu__list\"",[309,1763,1764],{"class":321}," aria-labelledby",[309,1766,1519],{"class":325},[309,1768,1741],{"class":1522},[309,1770,1531],{"class":325},[309,1772,1773,1776,1778,1781,1784,1786,1789,1792,1794,1797,1800,1803,1805,1808,1810],{"class":140,"line":832},[309,1774,1775],{"class":325},"      \u003C",[309,1777,38],{"class":1344},[309,1779,1780],{"class":325},">\u003C",[309,1782,1783],{"class":1344},"label",[309,1785,1780],{"class":325},[309,1787,1788],{"class":1344},"input",[309,1790,1791],{"class":321}," type",[309,1793,1519],{"class":325},[309,1795,1796],{"class":1522},"\"checkbox\"",[309,1798,1799],{"class":321}," checked",[309,1801,1802],{"class":325},"> In stock\u003C\u002F",[309,1804,1783],{"class":1344},[309,1806,1807],{"class":325},">\u003C\u002F",[309,1809,38],{"class":1344},[309,1811,1531],{"class":325},[309,1813,1814,1816,1818,1820,1822,1824,1826,1828,1830,1832,1835,1837,1839,1841],{"class":140,"line":960},[309,1815,1775],{"class":325},[309,1817,38],{"class":1344},[309,1819,1780],{"class":325},[309,1821,1783],{"class":1344},[309,1823,1780],{"class":325},[309,1825,1788],{"class":1344},[309,1827,1791],{"class":321},[309,1829,1519],{"class":325},[309,1831,1796],{"class":1522},[309,1833,1834],{"class":325},"> On sale\u003C\u002F",[309,1836,1783],{"class":1344},[309,1838,1807],{"class":325},[309,1840,38],{"class":1344},[309,1842,1531],{"class":325},[309,1844,1845,1847,1849,1851,1853,1855,1857,1859,1861,1863,1866,1868,1870,1872],{"class":140,"line":977},[309,1846,1775],{"class":325},[309,1848,38],{"class":1344},[309,1850,1780],{"class":325},[309,1852,1783],{"class":1344},[309,1854,1780],{"class":325},[309,1856,1788],{"class":1344},[309,1858,1791],{"class":321},[309,1860,1519],{"class":325},[309,1862,1796],{"class":1522},[309,1864,1865],{"class":325},"> New arrivals\u003C\u002F",[309,1867,1783],{"class":1344},[309,1869,1807],{"class":325},[309,1871,38],{"class":1344},[309,1873,1531],{"class":325},[309,1875,1876,1879,1881],{"class":140,"line":996},[309,1877,1878],{"class":325},"    \u003C\u002F",[309,1880,35],{"class":1344},[309,1882,1531],{"class":325},[309,1884,1885,1887,1889],{"class":140,"line":1015},[309,1886,1691],{"class":325},[309,1888,1538],{"class":1344},[309,1890,1531],{"class":325},[309,1892,1893,1896,1898],{"class":140,"line":1031},[309,1894,1895],{"class":325},"\u003C\u002F",[309,1897,1538],{"class":1344},[309,1899,1531],{"class":325},[300,1901,1903],{"className":302,"code":1902,"language":304,"meta":305,"style":305},".filter-btn {\n  \u002F* Publishes the reference frame. No visual effect on the button itself. *\u002F\n  anchor-name: --filter-btn;\n  display: inline-flex;\n  gap: 0.4rem;\n  align-items: center;\n  font: inherit;\n  padding: 0.5rem 0.9rem;\n  border: 1px solid #d3d8e0;\n  border-radius: 0.5rem;\n  background: #fff;\n}\n\n.filter-menu {\n  \u002F* Popover elements default to position: fixed and margin: auto in the UA\n     sheet; both are reset here so our own placement wins predictably. *\u002F\n  position: fixed;\n  margin: 0;\n  position-anchor: --filter-btn;\n\n  \u002F* Below the button, aligned to its inline-start edge, growing outwards. *\u002F\n  position-area: block-end span-inline-end;\n\n  \u002F* Try above, then mirrored, then the diagonal, before giving up. *\u002F\n  position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;\n\n  \u002F* Never narrower than the button; never wider than a readable measure. *\u002F\n  min-width: anchor-size(width);\n  max-width: 22rem;\n\n  \u002F* Never taller than the space between the button and the viewport edge. *\u002F\n  max-height: calc(100vh - anchor(bottom) - 1rem);\n  overflow-y: auto;\n\n  \u002F* Hide it entirely once the button scrolls out of the scrollport. *\u002F\n  position-visibility: anchors-visible;\n\n  margin-block-start: 0.4rem;\n  padding: 0.75rem;\n  border: 1px solid #d3d8e0;\n  border-radius: 0.6rem;\n  background: #fff;\n  box-shadow: 0 12px 32px rgb(15 23 42 \u002F 0.16);\n}\n\n\u002F* Entry and exit. display and overlay are discrete properties, so they need\n   allow-discrete to participate in the transition at all. *\u002F\n.filter-menu {\n  opacity: 0;\n  translate: 0 -0.4rem;\n  transition:\n    opacity 0.18s ease,\n    translate 0.18s ease,\n    display 0.18s allow-discrete,\n    overlay 0.18s allow-discrete;\n}\n\n.filter-menu:popover-open {\n  opacity: 1;\n  translate: 0 0;\n}\n\n\u002F* The pre-open state, required because the element goes from display:none\n   straight to its open state with no prior computed value to animate from. *\u002F\n@starting-style {\n  .filter-menu:popover-open {\n    opacity: 0;\n    translate: 0 -0.4rem;\n  }\n}\n\n.filter-menu__label { margin: 0 0 0.5rem; font-weight: 600; }\n.filter-menu__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.4rem; }\n.filter-menu__list label { display: flex; gap: 0.5rem; align-items: center; }\n\n@media (prefers-reduced-motion: reduce) {\n  .filter-menu { transition: display 0.18s allow-discrete, overlay 0.18s allow-discrete; translate: none; }\n  .filter-menu:popover-open { translate: none; }\n}\n",[18,1904,1905,1912,1917,1924,1936,1950,1961,1973,1991,2012,2025,2037,2041,2045,2052,2057,2062,2073,2085,2092,2097,2103,2114,2119,2125,2132,2137,2143,2150,2164,2169,2175,2211,2223,2228,2234,2243,2248,2261,2275,2292,2306,2317,2359,2364,2369,2375,2381,2388,2400,2417,2426,2443,2457,2470,2484,2489,2494,2507,2518,2532,2537,2542,2548,2554,2561,2573,2585,2601,2607,2612,2617,2652,2707,2745,2750,2759,2798,2817],{"__ignoreMap":305},[309,1906,1907,1910],{"class":140,"line":311},[309,1908,1909],{"class":321},".filter-btn",[309,1911,353],{"class":325},[309,1913,1914],{"class":140,"line":318},[309,1915,1916],{"class":314},"  \u002F* Publishes the reference frame. No visual effect on the button itself. *\u002F\n",[309,1918,1919,1921],{"class":140,"line":334},[309,1920,763],{"class":321},[309,1922,1923],{"class":325},": --filter-btn;\n",[309,1925,1926,1929,1931,1934],{"class":140,"line":341},[309,1927,1928],{"class":321},"  display",[309,1930,362],{"class":325},[309,1932,1933],{"class":321},"inline-flex",[309,1935,368],{"class":325},[309,1937,1938,1941,1943,1946,1948],{"class":140,"line":347},[309,1939,1940],{"class":321},"  gap",[309,1942,362],{"class":325},[309,1944,1945],{"class":321},"0.4",[309,1947,827],{"class":826},[309,1949,368],{"class":325},[309,1951,1952,1955,1957,1959],{"class":140,"line":356},[309,1953,1954],{"class":321},"  align-items",[309,1956,362],{"class":325},[309,1958,515],{"class":321},[309,1960,368],{"class":325},[309,1962,1963,1966,1968,1971],{"class":140,"line":371},[309,1964,1965],{"class":321},"  font",[309,1967,362],{"class":325},[309,1969,1970],{"class":321},"inherit",[309,1972,368],{"class":325},[309,1974,1975,1978,1980,1982,1984,1987,1989],{"class":140,"line":380},[309,1976,1977],{"class":321},"  padding",[309,1979,362],{"class":325},[309,1981,823],{"class":321},[309,1983,827],{"class":826},[309,1985,1986],{"class":321}," 0.9",[309,1988,827],{"class":826},[309,1990,368],{"class":325},[309,1992,1993,1996,1998,2001,2004,2007,2010],{"class":140,"line":815},[309,1994,1995],{"class":321},"  border",[309,1997,362],{"class":325},[309,1999,2000],{"class":321},"1",[309,2002,2003],{"class":826},"px",[309,2005,2006],{"class":321}," solid",[309,2008,2009],{"class":321}," #d3d8e0",[309,2011,368],{"class":325},[309,2013,2014,2017,2019,2021,2023],{"class":140,"line":832},[309,2015,2016],{"class":321},"  border-radius",[309,2018,362],{"class":325},[309,2020,823],{"class":321},[309,2022,827],{"class":826},[309,2024,368],{"class":325},[309,2026,2027,2030,2032,2035],{"class":140,"line":960},[309,2028,2029],{"class":321},"  background",[309,2031,362],{"class":325},[309,2033,2034],{"class":321},"#fff",[309,2036,368],{"class":325},[309,2038,2039],{"class":140,"line":977},[309,2040,383],{"class":325},[309,2042,2043],{"class":140,"line":996},[309,2044,338],{"emptyLinePlaceholder":337},[309,2046,2047,2050],{"class":140,"line":1015},[309,2048,2049],{"class":321},".filter-menu",[309,2051,353],{"class":325},[309,2053,2054],{"class":140,"line":1031},[309,2055,2056],{"class":314},"  \u002F* Popover elements default to position: fixed and margin: auto in the UA\n",[309,2058,2059],{"class":140,"line":1049},[309,2060,2061],{"class":314},"     sheet; both are reset here so our own placement wins predictably. *\u002F\n",[309,2063,2065,2067,2069,2071],{"class":140,"line":2064},17,[309,2066,359],{"class":321},[309,2068,362],{"class":325},[309,2070,365],{"class":321},[309,2072,368],{"class":325},[309,2074,2076,2078,2080,2083],{"class":140,"line":2075},18,[309,2077,907],{"class":321},[309,2079,362],{"class":325},[309,2081,2082],{"class":321},"0",[309,2084,368],{"class":325},[309,2086,2088,2090],{"class":140,"line":2087},19,[309,2089,374],{"class":321},[309,2091,1923],{"class":325},[309,2093,2095],{"class":140,"line":2094},20,[309,2096,338],{"emptyLinePlaceholder":337},[309,2098,2100],{"class":140,"line":2099},21,[309,2101,2102],{"class":314},"  \u002F* Below the button, aligned to its inline-start edge, growing outwards. *\u002F\n",[309,2104,2106,2108,2110,2112],{"class":140,"line":2105},22,[309,2107,802],{"class":321},[309,2109,362],{"class":325},[309,2111,807],{"class":321},[309,2113,1300],{"class":325},[309,2115,2117],{"class":140,"line":2116},23,[309,2118,338],{"emptyLinePlaceholder":337},[309,2120,2122],{"class":140,"line":2121},24,[309,2123,2124],{"class":314},"  \u002F* Try above, then mirrored, then the diagonal, before giving up. *\u002F\n",[309,2126,2128,2130],{"class":140,"line":2127},25,[309,2129,1305],{"class":321},[309,2131,1308],{"class":325},[309,2133,2135],{"class":140,"line":2134},26,[309,2136,338],{"emptyLinePlaceholder":337},[309,2138,2140],{"class":140,"line":2139},27,[309,2141,2142],{"class":314},"  \u002F* Never narrower than the button; never wider than a readable measure. *\u002F\n",[309,2144,2146,2148],{"class":140,"line":2145},28,[309,2147,1199],{"class":321},[309,2149,1189],{"class":325},[309,2151,2153,2155,2157,2160,2162],{"class":140,"line":2152},29,[309,2154,1186],{"class":321},[309,2156,362],{"class":325},[309,2158,2159],{"class":321},"22",[309,2161,827],{"class":826},[309,2163,368],{"class":325},[309,2165,2167],{"class":140,"line":2166},30,[309,2168,338],{"emptyLinePlaceholder":337},[309,2170,2172],{"class":140,"line":2171},31,[309,2173,2174],{"class":314},"  \u002F* Never taller than the space between the button and the viewport edge. *\u002F\n",[309,2176,2178,2181,2183,2185,2188,2191,2194,2197,2200,2202,2205,2207,2209],{"class":140,"line":2177},32,[309,2179,2180],{"class":321},"  max-height",[309,2182,362],{"class":325},[309,2184,1204],{"class":321},[309,2186,2187],{"class":325},"(",[309,2189,2190],{"class":321},"100",[309,2192,2193],{"class":826},"vh",[309,2195,2196],{"class":826}," -",[309,2198,2199],{"class":325}," anchor(",[309,2201,534],{"class":321},[309,2203,2204],{"class":325},") - ",[309,2206,2000],{"class":321},[309,2208,827],{"class":826},[309,2210,1160],{"class":325},[309,2212,2214,2217,2219,2221],{"class":140,"line":2213},33,[309,2215,2216],{"class":321},"  overflow-y",[309,2218,362],{"class":325},[309,2220,495],{"class":321},[309,2222,368],{"class":325},[309,2224,2226],{"class":140,"line":2225},34,[309,2227,338],{"emptyLinePlaceholder":337},[309,2229,2231],{"class":140,"line":2230},35,[309,2232,2233],{"class":314},"  \u002F* Hide it entirely once the button scrolls out of the scrollport. *\u002F\n",[309,2235,2237,2240],{"class":140,"line":2236},36,[309,2238,2239],{"class":321},"  position-visibility",[309,2241,2242],{"class":325},": anchors-visible;\n",[309,2244,2246],{"class":140,"line":2245},37,[309,2247,338],{"emptyLinePlaceholder":337},[309,2249,2251,2253,2255,2257,2259],{"class":140,"line":2250},38,[309,2252,818],{"class":321},[309,2254,362],{"class":325},[309,2256,1945],{"class":321},[309,2258,827],{"class":826},[309,2260,368],{"class":325},[309,2262,2264,2266,2268,2271,2273],{"class":140,"line":2263},39,[309,2265,1977],{"class":321},[309,2267,362],{"class":325},[309,2269,2270],{"class":321},"0.75",[309,2272,827],{"class":826},[309,2274,368],{"class":325},[309,2276,2278,2280,2282,2284,2286,2288,2290],{"class":140,"line":2277},40,[309,2279,1995],{"class":321},[309,2281,362],{"class":325},[309,2283,2000],{"class":321},[309,2285,2003],{"class":826},[309,2287,2006],{"class":321},[309,2289,2009],{"class":321},[309,2291,368],{"class":325},[309,2293,2295,2297,2299,2302,2304],{"class":140,"line":2294},41,[309,2296,2016],{"class":321},[309,2298,362],{"class":325},[309,2300,2301],{"class":321},"0.6",[309,2303,827],{"class":826},[309,2305,368],{"class":325},[309,2307,2309,2311,2313,2315],{"class":140,"line":2308},42,[309,2310,2029],{"class":321},[309,2312,362],{"class":325},[309,2314,2034],{"class":321},[309,2316,368],{"class":325},[309,2318,2320,2323,2325,2327,2330,2332,2335,2337,2340,2342,2345,2348,2351,2354,2357],{"class":140,"line":2319},43,[309,2321,2322],{"class":321},"  box-shadow",[309,2324,362],{"class":325},[309,2326,2082],{"class":321},[309,2328,2329],{"class":321}," 12",[309,2331,2003],{"class":826},[309,2333,2334],{"class":321}," 32",[309,2336,2003],{"class":826},[309,2338,2339],{"class":321}," rgb",[309,2341,2187],{"class":325},[309,2343,2344],{"class":321},"15",[309,2346,2347],{"class":321}," 23",[309,2349,2350],{"class":321}," 42",[309,2352,2353],{"class":325}," \u002F ",[309,2355,2356],{"class":321},"0.16",[309,2358,1160],{"class":325},[309,2360,2362],{"class":140,"line":2361},44,[309,2363,383],{"class":325},[309,2365,2367],{"class":140,"line":2366},45,[309,2368,338],{"emptyLinePlaceholder":337},[309,2370,2372],{"class":140,"line":2371},46,[309,2373,2374],{"class":314},"\u002F* Entry and exit. display and overlay are discrete properties, so they need\n",[309,2376,2378],{"class":140,"line":2377},47,[309,2379,2380],{"class":314},"   allow-discrete to participate in the transition at all. *\u002F\n",[309,2382,2384,2386],{"class":140,"line":2383},48,[309,2385,2049],{"class":321},[309,2387,353],{"class":325},[309,2389,2391,2394,2396,2398],{"class":140,"line":2390},49,[309,2392,2393],{"class":321},"  opacity",[309,2395,362],{"class":325},[309,2397,2082],{"class":321},[309,2399,368],{"class":325},[309,2401,2403,2406,2408,2410,2413,2415],{"class":140,"line":2402},50,[309,2404,2405],{"class":321},"  translate",[309,2407,362],{"class":325},[309,2409,2082],{"class":321},[309,2411,2412],{"class":321}," -0.4",[309,2414,827],{"class":826},[309,2416,368],{"class":325},[309,2418,2420,2423],{"class":140,"line":2419},51,[309,2421,2422],{"class":321},"  transition",[309,2424,2425],{"class":325},":\n",[309,2427,2429,2432,2434,2437,2440],{"class":140,"line":2428},52,[309,2430,2431],{"class":325},"    opacity ",[309,2433,108],{"class":321},[309,2435,2436],{"class":826},"s",[309,2438,2439],{"class":321}," ease",[309,2441,2442],{"class":325},",\n",[309,2444,2446,2449,2451,2453,2455],{"class":140,"line":2445},53,[309,2447,2448],{"class":325},"    translate ",[309,2450,108],{"class":321},[309,2452,2436],{"class":826},[309,2454,2439],{"class":321},[309,2456,2442],{"class":325},[309,2458,2460,2463,2465,2467],{"class":140,"line":2459},54,[309,2461,2462],{"class":325},"    display ",[309,2464,108],{"class":321},[309,2466,2436],{"class":826},[309,2468,2469],{"class":325}," allow-discrete,\n",[309,2471,2473,2476,2479,2481],{"class":140,"line":2472},55,[309,2474,2475],{"class":321},"    overlay",[309,2477,2478],{"class":321}," 0.18",[309,2480,2436],{"class":826},[309,2482,2483],{"class":325}," allow-discrete;\n",[309,2485,2487],{"class":140,"line":2486},56,[309,2488,383],{"class":325},[309,2490,2492],{"class":140,"line":2491},57,[309,2493,338],{"emptyLinePlaceholder":337},[309,2495,2497,2499,2502,2505],{"class":140,"line":2496},58,[309,2498,2049],{"class":321},[309,2500,2501],{"class":325},":",[309,2503,2504],{"class":1344},"popover-open",[309,2506,353],{"class":325},[309,2508,2510,2512,2514,2516],{"class":140,"line":2509},59,[309,2511,2393],{"class":321},[309,2513,362],{"class":325},[309,2515,2000],{"class":321},[309,2517,368],{"class":325},[309,2519,2521,2523,2525,2527,2530],{"class":140,"line":2520},60,[309,2522,2405],{"class":321},[309,2524,362],{"class":325},[309,2526,2082],{"class":321},[309,2528,2529],{"class":321}," 0",[309,2531,368],{"class":325},[309,2533,2535],{"class":140,"line":2534},61,[309,2536,383],{"class":325},[309,2538,2540],{"class":140,"line":2539},62,[309,2541,338],{"emptyLinePlaceholder":337},[309,2543,2545],{"class":140,"line":2544},63,[309,2546,2547],{"class":314},"\u002F* The pre-open state, required because the element goes from display:none\n",[309,2549,2551],{"class":140,"line":2550},64,[309,2552,2553],{"class":314},"   straight to its open state with no prior computed value to animate from. *\u002F\n",[309,2555,2557,2559],{"class":140,"line":2556},65,[309,2558,278],{"class":826},[309,2560,353],{"class":325},[309,2562,2564,2567,2569,2571],{"class":140,"line":2563},66,[309,2565,2566],{"class":321},"  .filter-menu",[309,2568,2501],{"class":325},[309,2570,2504],{"class":1344},[309,2572,353],{"class":325},[309,2574,2576,2579,2581,2583],{"class":140,"line":2575},67,[309,2577,2578],{"class":321},"    opacity",[309,2580,362],{"class":325},[309,2582,2082],{"class":321},[309,2584,368],{"class":325},[309,2586,2588,2591,2593,2595,2597,2599],{"class":140,"line":2587},68,[309,2589,2590],{"class":321},"    translate",[309,2592,362],{"class":325},[309,2594,2082],{"class":321},[309,2596,2412],{"class":321},[309,2598,827],{"class":826},[309,2600,368],{"class":325},[309,2602,2604],{"class":140,"line":2603},69,[309,2605,2606],{"class":325},"  }\n",[309,2608,2610],{"class":140,"line":2609},70,[309,2611,383],{"class":325},[309,2613,2615],{"class":140,"line":2614},71,[309,2616,338],{"emptyLinePlaceholder":337},[309,2618,2620,2623,2625,2628,2630,2632,2634,2637,2639,2642,2645,2647,2650],{"class":140,"line":2619},72,[309,2621,2622],{"class":321},".filter-menu__label",[309,2624,326],{"class":325},[309,2626,2627],{"class":321},"margin",[309,2629,362],{"class":325},[309,2631,2082],{"class":321},[309,2633,2529],{"class":321},[309,2635,2636],{"class":321}," 0.5",[309,2638,827],{"class":826},[309,2640,2641],{"class":325},"; ",[309,2643,2644],{"class":321},"font-weight",[309,2646,362],{"class":325},[309,2648,2649],{"class":321},"600",[309,2651,957],{"class":325},[309,2653,2655,2658,2660,2662,2664,2666,2668,2671,2673,2675,2677,2680,2682,2684,2686,2689,2691,2694,2696,2699,2701,2703,2705],{"class":140,"line":2654},73,[309,2656,2657],{"class":321},".filter-menu__list",[309,2659,326],{"class":325},[309,2661,2627],{"class":321},[309,2663,362],{"class":325},[309,2665,2082],{"class":321},[309,2667,2641],{"class":325},[309,2669,2670],{"class":321},"padding",[309,2672,362],{"class":325},[309,2674,2082],{"class":321},[309,2676,2641],{"class":325},[309,2678,2679],{"class":321},"list-style",[309,2681,362],{"class":325},[309,2683,160],{"class":321},[309,2685,2641],{"class":325},[309,2687,2688],{"class":321},"display",[309,2690,362],{"class":325},[309,2692,2693],{"class":321},"grid",[309,2695,2641],{"class":325},[309,2697,2698],{"class":321},"gap",[309,2700,362],{"class":325},[309,2702,1945],{"class":321},[309,2704,827],{"class":826},[309,2706,957],{"class":325},[309,2708,2710,2712,2715,2717,2719,2721,2724,2726,2728,2730,2732,2734,2736,2739,2741,2743],{"class":140,"line":2709},74,[309,2711,2657],{"class":321},[309,2713,2714],{"class":1344}," label",[309,2716,326],{"class":325},[309,2718,2688],{"class":321},[309,2720,362],{"class":325},[309,2722,2723],{"class":321},"flex",[309,2725,2641],{"class":325},[309,2727,2698],{"class":321},[309,2729,362],{"class":325},[309,2731,823],{"class":321},[309,2733,827],{"class":826},[309,2735,2641],{"class":325},[309,2737,2738],{"class":321},"align-items",[309,2740,362],{"class":325},[309,2742,515],{"class":321},[309,2744,957],{"class":325},[309,2746,2748],{"class":140,"line":2747},75,[309,2749,338],{"emptyLinePlaceholder":337},[309,2751,2753,2756],{"class":140,"line":2752},76,[309,2754,2755],{"class":826},"@media",[309,2757,2758],{"class":325}," (prefers-reduced-motion: reduce) {\n",[309,2760,2762,2764,2766,2769,2772,2774,2776,2779,2782,2784,2786,2789,2792,2794,2796],{"class":140,"line":2761},77,[309,2763,2566],{"class":321},[309,2765,326],{"class":325},[309,2767,2768],{"class":321},"transition",[309,2770,2771],{"class":325},": display ",[309,2773,108],{"class":321},[309,2775,2436],{"class":826},[309,2777,2778],{"class":325}," allow-discrete, ",[309,2780,2781],{"class":321},"overlay",[309,2783,2478],{"class":321},[309,2785,2436],{"class":826},[309,2787,2788],{"class":325}," allow-discrete; ",[309,2790,2791],{"class":321},"translate",[309,2793,362],{"class":325},[309,2795,160],{"class":321},[309,2797,957],{"class":325},[309,2799,2801,2803,2805,2807,2809,2811,2813,2815],{"class":140,"line":2800},78,[309,2802,2566],{"class":321},[309,2804,2501],{"class":325},[309,2806,2504],{"class":1344},[309,2808,326],{"class":325},[309,2810,2791],{"class":321},[309,2812,362],{"class":325},[309,2814,160],{"class":321},[309,2816,957],{"class":325},[309,2818,2820],{"class":140,"line":2819},79,[309,2821,383],{"class":325},[14,2823,2824,2825,2828,2829,2832,2833,2836,2837,2839,2840,2842,2843,2846,2847,2850,2851,64,2855,289],{},"Three details in there repay attention. The ",[18,2826,2827],{},"margin: 0"," reset matters because the user-agent stylesheet gives ",[18,2830,2831],{},"[popover]"," a centring ",[18,2834,2835],{},"margin: auto",", which fights ",[18,2838,53],{}," in confusing ways. The ",[18,2841,2781],{}," property in the transition list is what keeps the element in the top layer for the duration of the exit animation — omit it and the panel drops out of the top layer instantly on close, so it appears to jump behind other content while fading. And ",[18,2844,2845],{},"max-height"," built from ",[18,2848,2849],{},"anchor(bottom)"," means the menu scrolls internally instead of being pushed off-screen when the list is long. The mechanics of discrete transitions are covered end to end in ",[23,2852,2854],{"href":2853},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete\u002F","transitioning display with allow-discrete",[23,2856,2858],{"href":2857},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations\u002F","@starting-style entry animations",[205,2860],{},[208,2862,2864],{"id":2863},"performance-and-accessibility-notes","Performance and accessibility notes",[14,2866,2867,2870,2871,2873,2874,2876],{},[31,2868,2869],{},"Layout cost is real but bounded."," Each fallback candidate the browser tries is an additional layout pass for that element's subtree. A three-candidate chain on a small dropdown is negligible; the same chain on twenty simultaneously-open anchored elements each containing a large subtree is not. Keep chains short, keep anchored subtrees small, and prefer ",[18,2872,53],{}," candidates over ",[18,2875,67],{}," blocks that also change sizing, since a size change can cascade into the subtree.",[14,2878,2879,2882,2883,412,2885,2887,2888,243,2891,64,2893,2896],{},[31,2880,2881],{},"Do not animate anchored placement."," Transitioning ",[18,2884,250],{},[18,2886,233],{}," on an anchored element forces layout every frame and fights the fallback machinery, which may pick a different candidate mid-transition. Animate ",[18,2889,2890],{},"opacity",[18,2892,2791],{},[18,2894,2895],{},"scale"," only — those stay on the compositor and never invalidate the placement.",[14,2898,2899,2902,2903,2906,2907,2910,2911,2914,2915,2919,2920,2924],{},[31,2900,2901],{},"Position is not semantics."," This is the accessibility headline for the entire feature. Anchor positioning moves pixels; it creates no relationship in the accessibility tree. A panel that visually hugs a button is, to a screen reader, an unrelated region somewhere in the DOM. You still need ",[18,2904,2905],{},"aria-describedby"," for descriptive popovers, ",[18,2908,2909],{},"aria-labelledby"," or an accessible name for panels, a real ",[18,2912,2913],{},"\u003Cbutton>"," as the trigger, and DOM order that puts the panel immediately after its trigger so that sequential navigation reaches it in a sane order. The ",[23,2916,2918],{"href":2917},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips\u002F","anchor positioned tooltips"," page works through the full association pattern, and the CSS-only approach in ",[23,2921,2923],{"href":2922},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips\u002F","accessible CSS-only tooltips"," covers the WCAG 1.4.13 requirements that apply either way.",[14,2926,2927,2930,2931,2934,2935,2938],{},[31,2928,2929],{},"Respect motion preferences."," Overlays that fly in from a distance are a documented vestibular trigger. Under ",[18,2932,2933],{},"prefers-reduced-motion: reduce",", keep the opacity fade and drop the translation, as the example above does — but keep the ",[18,2936,2937],{},"allow-discrete"," entries in the transition list, or the element will vanish before the exit finishes.",[14,2940,2941,275,2944,2946,2947,2949,2950,2952,2953,2955],{},[31,2942,2943],{},"Focus order still needs care.",[18,2945,73],{}," handles ",[1560,2948,1562],{}," and light dismiss, and it moves focus back to the invoker on close, but it does not trap focus (that is ",[18,2951,1490],{}," with ",[18,2954,1494],{},"). For a non-modal menu that is correct behaviour, not a bug.",[205,2957],{},[208,2959,2961],{"id":2960},"devtools-debugging-workflow","DevTools debugging workflow",[403,2963,2964,2973,2990,2999,3012,3026],{},[38,2965,2966,2969,2970,2972],{},[31,2967,2968],{},"Confirm the binding."," Select the anchored element in the Elements panel. In Chrome DevTools, a ",[18,2971,47],{}," declaration whose name resolves shows a small anchor badge next to it; hovering the badge highlights the anchor element in the viewport. No badge means the name did not resolve — check tree order and spelling of the dashed ident.",[38,2974,2975,2978,2979,2982,2983,412,2986,2989],{},[31,2976,2977],{},"Check the element is out of flow."," In Computed styles, filter for ",[18,2980,2981],{},"position",". If it reads ",[18,2984,2985],{},"static",[18,2987,2988],{},"relative",", every anchor property on the element is inert. This is the most common cause of \"my rule does nothing.\"",[38,2991,2992,2995,2996,2998],{},[31,2993,2994],{},"Watch the fallback chain fire."," With the element selected, drag the DevTools window edge to shrink the viewport and watch the Computed panel. The applied ",[18,2997,53],{}," changes as candidates are tried, so you can see exactly which candidate won at a given size.",[38,3000,3001,3004,3005,3008,3009,3011],{},[31,3002,3003],{},"Inspect the top layer."," In the Elements tree, a shown popover is annotated with a ",[18,3006,3007],{},"#top-layer"," marker; expanding it shows both the element and its ",[18,3010,1571],{},". If your popover is not listed there, it never opened.",[38,3013,3014,3017,3018,3021,3022,3025],{},[31,3015,3016],{},"Force the open state."," Use the ",[18,3019,3020],{},":hov"," pane to force ",[18,3023,3024],{},":popover-open"," so you can style the panel without it light-dismissing every time you click into DevTools.",[38,3027,3028,3031],{},[31,3029,3030],{},"Profile if placement feels janky."," Record in the Performance panel while scrolling a page with anchored elements. Repeated \"Layout\" entries attributed to the anchored subtree point at an over-long fallback chain or at animated insets.",[205,3033],{},[208,3035,3037],{"id":3036},"browser-compatibility","Browser compatibility",[441,3039,3040,3059],{},[444,3041,3042],{},[447,3043,3044,3047,3050,3053,3056],{},[450,3045,3046],{},"Feature",[450,3048,3049],{},"Chrome",[450,3051,3052],{},"Edge",[450,3054,3055],{},"Safari",[450,3057,3058],{},"Firefox",[460,3060,3061,3080,3095,3112,3129,3145],{},[447,3062,3063,3069,3072,3074,3077],{},[465,3064,3065,2353,3067],{},[18,3066,43],{},[18,3068,47],{},[465,3070,3071],{},"125+",[465,3073,3071],{},[465,3075,3076],{},"26+",[465,3078,3079],{},"147+",[447,3081,3082,3086,3089,3091,3093],{},[465,3083,3084],{},[18,3085,53],{},[465,3087,3088],{},"129+",[465,3090,3088],{},[465,3092,3076],{},[465,3094,3079],{},[447,3096,3097,3103,3106,3108,3110],{},[465,3098,3099,2353,3101],{},[18,3100,63],{},[18,3102,67],{},[465,3104,3105],{},"128+",[465,3107,3105],{},[465,3109,3076],{},[465,3111,3079],{},[447,3113,3114,3119,3122,3124,3127],{},[465,3115,3116,3118],{},[18,3117,73],{}," attribute",[465,3120,3121],{},"114+",[465,3123,3121],{},[465,3125,3126],{},"17+",[465,3128,3071],{},[447,3130,3131,3135,3138,3140,3143],{},[465,3132,3133],{},[18,3134,278],{},[465,3136,3137],{},"117+",[465,3139,3137],{},[465,3141,3142],{},"17.5+",[465,3144,3088],{},[447,3146,3147,3151,3153,3155,3158],{},[465,3148,3149],{},[18,3150,281],{},[465,3152,3137],{},[465,3154,3137],{},[465,3156,3157],{},"17.4+",[465,3159,3088],{},[14,3161,3162,3163,3165,3166,3168,3169,3171,3172,64,3174,3176,3177,3180,3181,3183],{},"The headline is that anchor positioning is no longer a one-engine experiment. Chrome and Edge shipped the binding properties in 125, with ",[18,3164,63],{}," following in 128 and ",[18,3167,53],{}," in 129 after the rename from ",[18,3170,721],{},". Safari shipped the feature in version 26, and Firefox shipped it in 147. ",[18,3173,57],{},[18,3175,587],{}," ship alongside the binding properties in each of those engines. Overlay ",[395,3178,3179],{},"behaviour"," — the ",[18,3182,73],{}," attribute and discrete transitions — has been interoperable for considerably longer, so the two halves of this section now have the same answer: they work everywhere current.",[14,3185,3186,3187,289],{},"What that changes is the shape of the fallback problem. You are no longer writing a second implementation for one hold-out engine; you are writing a graceful floor for the older versions still in circulation — anything below Chrome\u002FEdge 129, Safari 26 or Firefox 147. That is a much cheaper obligation, and it is the subject of ",[23,3188,3190],{"href":3189},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks\u002F","anchor positioning fallbacks",[205,3192],{},[208,3194,3196],{"id":3195},"common-pitfalls","Common pitfalls",[441,3198,3199,3212],{},[444,3200,3201],{},[447,3202,3203,3206,3209],{},[450,3204,3205],{},"Pitfall",[450,3207,3208],{},"Cause",[450,3210,3211],{},"Resolution",[460,3213,3214,3237,3260,3283,3300],{},[447,3215,3216,3219,3227],{},[465,3217,3218],{},"Anchor properties have no effect",[465,3220,3221,3222,412,3225],{},"The anchored element is still ",[18,3223,3224],{},"position: static",[18,3226,2988],{},[465,3228,3229,3230,3232,3233,3236],{},"Set ",[18,3231,229],{}," (or ",[18,3234,3235],{},"absolute",") on the anchored element; anchor placement only applies to out-of-flow boxes.",[447,3238,3239,3245,3254],{},[465,3240,3241,3242,3244],{},"Popover ignores ",[18,3243,53],{}," and sits centred",[465,3246,3247,3248,3250,3251,3253],{},"The UA stylesheet's ",[18,3249,2835],{}," on ",[18,3252,2831],{}," is still in effect",[465,3255,3256,3257,3259],{},"Declare ",[18,3258,2827],{}," on the popover, then add directional margins for the gap you want.",[447,3261,3262,3265,3270],{},[465,3263,3264],{},"Panel jumps behind other content while closing",[465,3266,3267,3269],{},[18,3268,2781],{}," is not in the transition list, so the element leaves the top layer immediately",[465,3271,3272,3273,3276,3277,3279,3280,3282],{},"Add ",[18,3274,3275],{},"overlay \u003Cduration> allow-discrete"," alongside ",[18,3278,2688],{}," in the ",[18,3281,2768],{}," declaration.",[447,3284,3285,3288,3294],{},[465,3286,3287],{},"Wrong element is used as the anchor in a list",[465,3289,3290,3291,3293],{},"Several instances share one ",[18,3292,43],{},"; the last in tree order wins",[465,3295,3296,3297,3299],{},"Give each instance a distinct name, or open the panel via ",[18,3298,1585],{}," and rely on the implicit anchor.",[447,3301,3302,3305,3312],{},[465,3303,3304],{},"Tooltip stays pinned at the scrollport edge pointing at nothing",[465,3306,3307,3308,3311],{},"Default ",[18,3309,3310],{},"position-visibility: always"," keeps it painted after the anchor scrolls away",[465,3313,3229,3314,3316],{},[18,3315,1418],{}," on the anchored element.",[205,3318],{},[208,3320,3322],{"id":3321},"faq","FAQ",[14,3324,3325,3328],{},[31,3326,3327],{},"Does anchor positioning replace positioning libraries entirely?","\nFor the common cases yes. Tethering, edge collision flipping, and size matching are all expressible in CSS now, and every current engine ships the feature. Libraries still earn their place for virtual anchors that follow a cursor, arrow elements that must stay clamped to the anchor edge in every fallback, and codebases whose support floor still includes browser versions released before the feature landed.",[14,3330,3331,3337,3338,3340],{},[31,3332,3333,3334,3336],{},"Do I need the ",[18,3335,73],{}," attribute to use anchor positioning?","\nNo. The two features are independent. Anchor positioning works on any absolutely or fixed positioned element, and ",[18,3339,73],{}," works without any anchor rules. They are designed to compose because a top-layer element has no positioned ancestor to anchor to, which is exactly the gap anchor positioning fills.",[14,3342,3343,3349,3350,243,3352,64,3354,3356,3357,3359,3360,412,3362,3364,3365,3367],{},[31,3344,3345,3346,3348],{},"Why does my anchored element ignore ",[18,3347,53],{},"?","\nAlmost always because it is not out of flow. ",[18,3351,53],{},[18,3353,57],{},[18,3355,63],{}," only apply to elements with ",[18,3358,2981],{}," set to ",[18,3361,3235],{},[18,3363,365],{},". A statically positioned element with a valid ",[18,3366,47],{}," still lays out normally.",[14,3369,3370,3373,3374,3376,3377,289],{},[31,3371,3372],{},"Can one anchor name be used by several elements?","\nYes, and this is the usual case in a list. If more than one element in scope carries the same ",[18,3375,43],{},", the anchored element resolves against the last one in tree order, so scope the name with a per-instance custom property or rely on the implicit anchor from ",[18,3378,1585],{},[205,3380],{},[208,3382,3384],{"id":3383},"related","Related",[35,3386,3387,3392,3398,3407,3413],{},[38,3388,3389,3391],{},[23,3390,26],{"href":25}," — the parent guide this section belongs to.",[38,3393,3394,3397],{},[23,3395,3396],{"href":2917},"Anchor positioned tooltips"," — a complete tethered tooltip with flipping and correct ARIA association.",[38,3399,3400,3403,3404,3406],{},[23,3401,3402],{"href":1566},"Popover attribute and CSS styling"," — light dismiss, ",[18,3405,1571],{},", and script-free entry animation.",[38,3408,3409,3412],{},[23,3410,3411],{"href":3189},"Anchor positioning fallbacks"," — a graceful floor for older browser versions without maintaining two components.",[38,3414,3415,3418],{},[23,3416,3417],{"href":2853},"Transitioning display with allow-discrete"," — cross-area: the transition mechanics every overlay depends on.",[3420,3421,3422],"style",{},"html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}",{"title":305,"searchDepth":318,"depth":318,"links":3424},[3425,3426,3427,3428,3436,3438,3439,3440,3441,3442,3443,3444],{"id":210,"depth":318,"text":211},{"id":294,"depth":318,"text":295},{"id":438,"depth":318,"text":439},{"id":733,"depth":318,"text":734,"children":3429},[3430,3431,3433,3435],{"id":738,"depth":334,"text":739},{"id":846,"depth":334,"text":3432},"Step 2 — Place coarsely with position-area",{"id":1096,"depth":334,"text":3434},"Step 3 — Place precisely with anchor()",{"id":1253,"depth":334,"text":1254},{"id":1424,"depth":318,"text":3437},"The top layer, and where popover comes in",{"id":1599,"depth":318,"text":1600},{"id":2863,"depth":318,"text":2864},{"id":2960,"depth":318,"text":2961},{"id":3036,"depth":318,"text":3037},{"id":3195,"depth":318,"text":3196},{"id":3321,"depth":318,"text":3322},{"id":3383,"depth":318,"text":3384},"CSS anchor positioning explained: anchor-name, position-anchor, position-area, the anchor() function, position-try-fallbacks, the top layer and popovers.","md",{"pageTitle":3448,"datePublished":3449,"dateModified":3449,"faq":3450},"CSS Anchor Positioning & Overlays","2026-07-20",[3451,3453,3456,3459],{"q":3327,"a":3452},"For the common cases yes. Tethering, edge collision flipping, and size matching are all expressible in CSS now, and every current engine ships the feature. Libraries still earn their place for virtual anchors that follow a cursor, arrow elements that must stay clamped to the anchor edge in every fallback, and codebases whose support floor still includes browser versions released before the feature landed.",{"q":3454,"a":3455},"Do I need the popover attribute to use anchor positioning?","No. The two features are independent. Anchor positioning works on any absolutely or fixed positioned element, and popover works without any anchor rules. They are designed to compose because a top-layer element has no positioned ancestor to anchor to, which is exactly the gap anchor positioning fills.",{"q":3457,"a":3458},"Why does my anchored element ignore position-area?","Almost always because it is not out of flow. position-area, anchor() and position-try-fallbacks only apply to elements with position set to absolute or fixed. A statically positioned element with a valid position-anchor still lays out normally.",{"q":3372,"a":3460},"Yes, and this is the usual case in a list. If more than one element in scope carries the same anchor-name, the anchored element resolves against the last one in tree order, so scope the name with a per-instance custom property or rely on the implicit anchor from popovertarget.","\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays",{"title":5,"description":3445},"mastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Findex","uDlFmBkfuneNhnkZ-L0MiJ9pAa7bPO8i7xbW75HWWlA",[3466,3469,3472,3475,3478,3481,3484,3487,3490,3493,3496,3499,3502,3505,3508,3511,3514,3517,3520,3523,3526,3529,3532,3535,3538,3541,3544,3547,3550,3553,3556,3559,3562,3565,3568,3571,3574,3577,3580,3583,3586,3589,3592,3595,3598,3601,3604,3606,3609,3612,3613,3616,3619,3622,3625,3628,3631,3634,3637,3640,3643,3646,3649,3652,3655,3658,3661,3664,3667,3670,3673,3675,3678,3681,3684,3687,3690,3693,3696,3699,3702,3705,3708,3711,3714,3717,3720,3723],{"path":3467,"title":3468},"\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":3470,"title":3471},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":3473,"title":3474},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":3476,"title":3477},"\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":3479,"title":3480},"\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":3482,"title":3483},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":3485,"title":3486},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":3488,"title":3489},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":3491,"title":3492},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":3494,"title":3495},"\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":3497,"title":3498},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":3500,"title":3501},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":3503,"title":3504},"\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":3506,"title":3507},"\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":3509,"title":3510},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":3512,"title":3513},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":3515,"title":3516},"\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":3518,"title":3519},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":3521,"title":3522},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":3524,"title":3525},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":3527,"title":3528},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":3530,"title":3531},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":3533,"title":3534},"\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":3536,"title":3537},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":3539,"title":3540},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":3542,"title":3543},"\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":3545,"title":3546},"\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":3548,"title":3549},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":3551,"title":3552},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":3554,"title":3555},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":3557,"title":3558},"\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":3560,"title":3561},"\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":3563,"title":3564},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":3566,"title":3567},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":3569,"title":3570},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":3572,"title":3573},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":3575,"title":3576},"\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":3578,"title":3579},"\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":3581,"title":3582},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":3584,"title":3585},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":3587,"title":3588},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":3590,"title":3591},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":3593,"title":3594},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":3596,"title":3597},"\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":3599,"title":3600},"\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":3602,"title":3603},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":531,"title":3605},"Modern CSS Layouts & Micro-Interactions",{"path":3607,"title":3608},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":3610,"title":3611},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":3461,"title":5},{"path":3614,"title":3615},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":3617,"title":3618},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":3620,"title":3621},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":3623,"title":3624},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":3626,"title":3627},"\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":3629,"title":3630},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":3632,"title":3633},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":3635,"title":3636},"\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":3638,"title":3639},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":3641,"title":3642},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":3644,"title":3645},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":3647,"title":3648},"\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":3650,"title":3651},"\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":3653,"title":3654},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":3656,"title":3657},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":3659,"title":3660},"\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":3662,"title":3663},"\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":3665,"title":3666},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":3668,"title":3669},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":3671,"title":3672},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":3674,"title":26},"\u002Fmastering-container-queries-responsive-layouts",{"path":3676,"title":3677},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":3679,"title":3680},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":3682,"title":3683},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":3685,"title":3686},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":3688,"title":3689},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":3691,"title":3692},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":3694,"title":3695},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":3697,"title":3698},"\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":3700,"title":3701},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":3703,"title":3704},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":3706,"title":3707},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":3709,"title":3710},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":3712,"title":3713},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":3715,"title":3716},"\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":3718,"title":3719},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":3721,"title":3722},"\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":3724,"title":3725},"\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",1784566156592]