[{"data":1,"prerenderedAt":1512},["ShallowReactive",2],{"page-\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips\u002F":3,"content-all-pages":1249},{"id":4,"title":5,"body":6,"description":1230,"extension":1231,"meta":1232,"navigation":346,"path":1245,"seo":1246,"stem":1247,"__hash__":1248},"content\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips\u002Findex.md","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"type":7,"value":8,"toc":1220},"minimark",[9,13,32,37,44,52,55,148,152,160,164,304,777,799,803,809,817,824,838,842,845,867,883,901,919,929,958,997,1001,1008,1073,1095,1099,1119,1123,1135,1158,1168,1178,1182,1216],[10,11,5],"h1",{"id":12},"anchor-positioned-tooltips-tethering-flipping-and-getting-the-semantics-right",[14,15,16,17,22,23,27,28,31],"p",{},"The narrow problem here is a familiar one with a new solution. You have a small explanatory bubble that should appear beside a trigger on hover and on keyboard focus, sit as close to that trigger as the layout allows, and — critically — not render half off the screen when the trigger happens to be the last item in a toolbar pressed against the right edge of a narrow phone. Historically the last requirement is what forced a JavaScript dependency into an otherwise trivial component. This page, part of the ",[18,19,21],"a",{"href":20},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002F","CSS anchor positioning and overlays"," section, builds that tooltip with ",[24,25,26],"code",{},"position-anchor"," for the tether and ",[24,29,30],{},"position-try-fallbacks"," for the collision handling, then spends real time on the part that CSS cannot help with at all: making the browser's accessibility tree agree with what the eye sees.",[33,34,36],"h2",{"id":35},"why-css-placement-and-what-it-does-not-buy-you","Why CSS placement, and what it does not buy you",[14,38,39,40,43],{},"The argument for moving placement into CSS is not primarily about bundle size, though a few kilobytes are pleasant to lose. It is about correctness under conditions your script never observes. A JavaScript positioner recalculates on the events it listens for — scroll, resize, maybe a ",[24,41,42],{},"ResizeObserver"," on the trigger. It does not recalculate when a web font swaps in and reflows the toolbar, when a sibling's image finally decodes, or when the user zooms text to 200% and the trigger moves. Anchor positioning is evaluated as part of layout itself, so it is correct on every frame by construction, including the frames your listeners never hear about.",[14,45,46,47,51],{},"The tradeoff is a recent one rather than a narrow one: Chrome and Edge shipped the feature in version 125, Safari in 26, and Firefox in 147. Every current engine has it, but the ship dates are new enough that older versions in circulation do not, so this is still best treated as a decoration on top of a placement that already works rather than the only placement you ship — the reasoning and the code for that split live in ",[18,48,50],{"href":49},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks\u002F","anchor positioning fallbacks",".",[14,53,54],{},"The other thing CSS placement does not buy you is meaning. This deserves stating bluntly because the visual result is so convincing that it is easy to stop there. Putting a box eight pixels above a button creates exactly zero relationship between them in the accessibility tree. A screen reader user tabbing to that button hears the button's label and nothing else; the bubble is a disconnected region living somewhere in the DOM. The tooltip needs two independent wires connected — one for pixels, one for semantics — and only the first is CSS's job.",[56,57,63,64,63,68,63,72,63,79,63,91,63,97,63,106,63,111,63,115,63,119,63,123,63,126,63,130,63,133,63,136,63,138,63,141,63,143],"svg",{"viewBox":58,"role":59,"ariaLabel":60,"xmlns":61,"style":62},"0 0 720 300","img","Visual placement and accessible association are two independent connections between a trigger and its tooltip","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[65,66,67],"title",{},"Two independent wires: placement and association",[69,70,71],"desc",{},"The left column shows the CSS properties that place the tooltip; the right column shows the HTML attributes that associate it with the trigger for assistive technology.",[73,74,78],"text",{"x":75,"y":76,"style":77},"360","28","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","Both wires must be connected",[80,81],"rect",{"x":82,"y":83,"width":84,"height":85,"rx":86,"fill":87,"stroke":88,"strokeWidth":89,"opacity":90},"30","52","310","196","10","none","currentColor","1.5","0.5",[73,92,96],{"x":93,"y":94,"style":95},"185","80","text-anchor:middle;fill:currentColor;font:13px sans-serif","where the box paints",[80,98],{"x":99,"y":100,"width":101,"height":102,"rx":103,"fill":104,"opacity":105},"54","98","262","44","6","#7aa2ff","0.2",[73,107,110],{"x":93,"y":108,"style":109},"125","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","anchor-name: --tip",[80,112],{"x":99,"y":113,"width":101,"height":102,"rx":103,"fill":104,"opacity":114},"176","0.3",[73,116,118],{"x":93,"y":117,"style":109},"203","position-anchor: --tip",[120,121],"line",{"x1":93,"y1":122,"x2":93,"y2":113,"stroke":88,"strokeWidth":89},"142",[80,124],{"x":125,"y":83,"width":84,"height":85,"rx":86,"fill":87,"stroke":88,"strokeWidth":89,"opacity":90},"380",[73,127,129],{"x":128,"y":94,"style":95},"535","what the screen reader hears",[80,131],{"x":132,"y":100,"width":101,"height":102,"rx":103,"fill":104,"opacity":105},"404",[73,134,135],{"x":128,"y":108,"style":109},"aria-describedby=\"t1\"",[80,137],{"x":132,"y":113,"width":101,"height":102,"rx":103,"fill":104,"opacity":114},[73,139,140],{"x":128,"y":117,"style":109},"id=\"t1\" role=\"tooltip\"",[120,142],{"x1":128,"y1":122,"x2":128,"y2":113,"stroke":88,"strokeWidth":89},[73,144,147],{"x":75,"y":145,"style":146},"278","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.7","CSS supplies the left column only; the right column is markup you must write",[33,149,151],{"id":150},"complete-working-implementation","Complete working implementation",[14,153,154,155,159],{},"Two triggers sit at opposite edges of the frame below. Focus one with ",[156,157,158],"kbd",{},"Tab"," or hover it, then drag the frame narrower: the bubbles flip rather than spill.",[161,162],"live-demo",{"name":163},"anchor-tooltip-flip",[165,166,171],"pre",{"className":167,"code":168,"language":169,"meta":170,"style":170},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cspan class=\"tt\">\n  \u003Cbutton type=\"button\" class=\"tt__trigger\" aria-describedby=\"tt-a\">\n    Retention policy\n  \u003C\u002Fbutton>\n  \u003Cspan role=\"tooltip\" id=\"tt-a\" class=\"tt__bubble\">\n    Records are purged 30 days after the account closes.\n  \u003C\u002Fspan>\n\u003C\u002Fspan>\n","html","",[24,172,173,198,232,238,248,279,285,294],{"__ignoreMap":170},[174,175,177,181,184,188,191,195],"span",{"class":120,"line":176},1,[174,178,180],{"class":179},"suds8","\u003C",[174,182,174],{"class":183},"sne4z",[174,185,187],{"class":186},"s-5SL"," class",[174,189,190],{"class":179},"=",[174,192,194],{"class":193},"sT6z2","\"tt\"",[174,196,197],{"class":179},">\n",[174,199,201,204,207,210,212,215,217,219,222,225,227,230],{"class":120,"line":200},2,[174,202,203],{"class":179},"  \u003C",[174,205,206],{"class":183},"button",[174,208,209],{"class":186}," type",[174,211,190],{"class":179},[174,213,214],{"class":193},"\"button\"",[174,216,187],{"class":186},[174,218,190],{"class":179},[174,220,221],{"class":193},"\"tt__trigger\"",[174,223,224],{"class":186}," aria-describedby",[174,226,190],{"class":179},[174,228,229],{"class":193},"\"tt-a\"",[174,231,197],{"class":179},[174,233,235],{"class":120,"line":234},3,[174,236,237],{"class":179},"    Retention policy\n",[174,239,241,244,246],{"class":120,"line":240},4,[174,242,243],{"class":179},"  \u003C\u002F",[174,245,206],{"class":183},[174,247,197],{"class":179},[174,249,251,253,255,258,260,263,266,268,270,272,274,277],{"class":120,"line":250},5,[174,252,203],{"class":179},[174,254,174],{"class":183},[174,256,257],{"class":186}," role",[174,259,190],{"class":179},[174,261,262],{"class":193},"\"tooltip\"",[174,264,265],{"class":186}," id",[174,267,190],{"class":179},[174,269,229],{"class":193},[174,271,187],{"class":186},[174,273,190],{"class":179},[174,275,276],{"class":193},"\"tt__bubble\"",[174,278,197],{"class":179},[174,280,282],{"class":120,"line":281},6,[174,283,284],{"class":179},"    Records are purged 30 days after the account closes.\n",[174,286,288,290,292],{"class":120,"line":287},7,[174,289,243],{"class":179},[174,291,174],{"class":183},[174,293,197],{"class":179},[174,295,297,300,302],{"class":120,"line":296},8,[174,298,299],{"class":179},"\u003C\u002F",[174,301,174],{"class":183},[174,303,197],{"class":179},[165,305,309],{"className":306,"code":307,"language":308,"meta":170,"style":170},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F* The wrapper exists only to keep trigger and bubble adjacent in the DOM.\n   It is NOT a containing block — anchor placement does not need one. *\u002F\n.tt { display: inline-block; }\n\n.tt__trigger {\n  \u002F* Publishes the reference frame. Purely declarative: nothing moves yet. *\u002F\n  anchor-name: --tt;\n  font: inherit;\n  padding: 0.4rem 0.7rem;\n  border: 1px solid #d3d8e0;\n  border-radius: 0.4rem;\n  background: #fff;\n}\n\n.tt__bubble {\n  \u002F* Fixed, not absolute: the anchor supplies the reference frame, so the\n     bubble follows the trigger on scroll and no ancestor can clip it. *\u002F\n  position: fixed;\n  position-anchor: --tt;\n\n  \u002F* Preferred placement: centred above the trigger. *\u002F\n  position-area: block-start center;\n\n  \u002F* If that overflows, try below, then mirrored, then diagonally. *\u002F\n  position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;\n\n  \u002F* One margin serves every candidate, because logical margins flip with\n     the placement. A hard-coded margin-bottom would not. *\u002F\n  margin: 0.4rem;\n\n  max-width: 14rem;\n  padding: 0.45rem 0.65rem;\n  border-radius: 0.45rem;\n  background: #1e2430;\n  color: #fff;\n  font-size: 0.8rem;\n\n  \u002F* Opacity-only reveal keeps the animation off the layout path, which\n     matters because the placement is recomputed during layout. *\u002F\n  opacity: 0;\n  transition: opacity 0.15s ease;\n}\n\n.tt__trigger:hover + .tt__bubble,\n.tt__trigger:focus-visible + .tt__bubble {\n  opacity: 1;\n}\n","css",[24,310,311,317,322,342,348,356,361,369,382,404,426,440,453,459,464,472,478,484,497,505,510,516,532,537,543,552,557,563,569,583,588,603,622,635,647,659,674,679,685,691,704,724,729,734,749,761,772],{"__ignoreMap":170},[174,312,313],{"class":120,"line":176},[174,314,316],{"class":315},"sLBg1","\u002F* The wrapper exists only to keep trigger and bubble adjacent in the DOM.\n",[174,318,319],{"class":120,"line":200},[174,320,321],{"class":315},"   It is NOT a containing block — anchor placement does not need one. *\u002F\n",[174,323,324,327,330,333,336,339],{"class":120,"line":234},[174,325,326],{"class":186},".tt",[174,328,329],{"class":179}," { ",[174,331,332],{"class":186},"display",[174,334,335],{"class":179},": ",[174,337,338],{"class":186},"inline-block",[174,340,341],{"class":179},"; }\n",[174,343,344],{"class":120,"line":240},[174,345,347],{"emptyLinePlaceholder":346},true,"\n",[174,349,350,353],{"class":120,"line":250},[174,351,352],{"class":186},".tt__trigger",[174,354,355],{"class":179}," {\n",[174,357,358],{"class":120,"line":281},[174,359,360],{"class":315},"  \u002F* Publishes the reference frame. Purely declarative: nothing moves yet. *\u002F\n",[174,362,363,366],{"class":120,"line":287},[174,364,365],{"class":186},"  anchor-name",[174,367,368],{"class":179},": --tt;\n",[174,370,371,374,376,379],{"class":120,"line":296},[174,372,373],{"class":186},"  font",[174,375,335],{"class":179},[174,377,378],{"class":186},"inherit",[174,380,381],{"class":179},";\n",[174,383,385,388,390,393,397,400,402],{"class":120,"line":384},9,[174,386,387],{"class":186},"  padding",[174,389,335],{"class":179},[174,391,392],{"class":186},"0.4",[174,394,396],{"class":395},"sHUrx","rem",[174,398,399],{"class":186}," 0.7",[174,401,396],{"class":395},[174,403,381],{"class":179},[174,405,407,410,412,415,418,421,424],{"class":120,"line":406},10,[174,408,409],{"class":186},"  border",[174,411,335],{"class":179},[174,413,414],{"class":186},"1",[174,416,417],{"class":395},"px",[174,419,420],{"class":186}," solid",[174,422,423],{"class":186}," #d3d8e0",[174,425,381],{"class":179},[174,427,429,432,434,436,438],{"class":120,"line":428},11,[174,430,431],{"class":186},"  border-radius",[174,433,335],{"class":179},[174,435,392],{"class":186},[174,437,396],{"class":395},[174,439,381],{"class":179},[174,441,443,446,448,451],{"class":120,"line":442},12,[174,444,445],{"class":186},"  background",[174,447,335],{"class":179},[174,449,450],{"class":186},"#fff",[174,452,381],{"class":179},[174,454,456],{"class":120,"line":455},13,[174,457,458],{"class":179},"}\n",[174,460,462],{"class":120,"line":461},14,[174,463,347],{"emptyLinePlaceholder":346},[174,465,467,470],{"class":120,"line":466},15,[174,468,469],{"class":186},".tt__bubble",[174,471,355],{"class":179},[174,473,475],{"class":120,"line":474},16,[174,476,477],{"class":315},"  \u002F* Fixed, not absolute: the anchor supplies the reference frame, so the\n",[174,479,481],{"class":120,"line":480},17,[174,482,483],{"class":315},"     bubble follows the trigger on scroll and no ancestor can clip it. *\u002F\n",[174,485,487,490,492,495],{"class":120,"line":486},18,[174,488,489],{"class":186},"  position",[174,491,335],{"class":179},[174,493,494],{"class":186},"fixed",[174,496,381],{"class":179},[174,498,500,503],{"class":120,"line":499},19,[174,501,502],{"class":186},"  position-anchor",[174,504,368],{"class":179},[174,506,508],{"class":120,"line":507},20,[174,509,347],{"emptyLinePlaceholder":346},[174,511,513],{"class":120,"line":512},21,[174,514,515],{"class":315},"  \u002F* Preferred placement: centred above the trigger. *\u002F\n",[174,517,519,522,524,527,530],{"class":120,"line":518},22,[174,520,521],{"class":186},"  position-area",[174,523,335],{"class":179},[174,525,526],{"class":186},"block-start",[174,528,529],{"class":186}," center",[174,531,381],{"class":179},[174,533,535],{"class":120,"line":534},23,[174,536,347],{"emptyLinePlaceholder":346},[174,538,540],{"class":120,"line":539},24,[174,541,542],{"class":315},"  \u002F* If that overflows, try below, then mirrored, then diagonally. *\u002F\n",[174,544,546,549],{"class":120,"line":545},25,[174,547,548],{"class":186},"  position-try-fallbacks",[174,550,551],{"class":179},": flip-block, flip-inline, flip-block flip-inline;\n",[174,553,555],{"class":120,"line":554},26,[174,556,347],{"emptyLinePlaceholder":346},[174,558,560],{"class":120,"line":559},27,[174,561,562],{"class":315},"  \u002F* One margin serves every candidate, because logical margins flip with\n",[174,564,566],{"class":120,"line":565},28,[174,567,568],{"class":315},"     the placement. A hard-coded margin-bottom would not. *\u002F\n",[174,570,572,575,577,579,581],{"class":120,"line":571},29,[174,573,574],{"class":186},"  margin",[174,576,335],{"class":179},[174,578,392],{"class":186},[174,580,396],{"class":395},[174,582,381],{"class":179},[174,584,586],{"class":120,"line":585},30,[174,587,347],{"emptyLinePlaceholder":346},[174,589,591,594,596,599,601],{"class":120,"line":590},31,[174,592,593],{"class":186},"  max-width",[174,595,335],{"class":179},[174,597,598],{"class":186},"14",[174,600,396],{"class":395},[174,602,381],{"class":179},[174,604,606,608,610,613,615,618,620],{"class":120,"line":605},32,[174,607,387],{"class":186},[174,609,335],{"class":179},[174,611,612],{"class":186},"0.45",[174,614,396],{"class":395},[174,616,617],{"class":186}," 0.65",[174,619,396],{"class":395},[174,621,381],{"class":179},[174,623,625,627,629,631,633],{"class":120,"line":624},33,[174,626,431],{"class":186},[174,628,335],{"class":179},[174,630,612],{"class":186},[174,632,396],{"class":395},[174,634,381],{"class":179},[174,636,638,640,642,645],{"class":120,"line":637},34,[174,639,445],{"class":186},[174,641,335],{"class":179},[174,643,644],{"class":186},"#1e2430",[174,646,381],{"class":179},[174,648,650,653,655,657],{"class":120,"line":649},35,[174,651,652],{"class":186},"  color",[174,654,335],{"class":179},[174,656,450],{"class":186},[174,658,381],{"class":179},[174,660,662,665,667,670,672],{"class":120,"line":661},36,[174,663,664],{"class":186},"  font-size",[174,666,335],{"class":179},[174,668,669],{"class":186},"0.8",[174,671,396],{"class":395},[174,673,381],{"class":179},[174,675,677],{"class":120,"line":676},37,[174,678,347],{"emptyLinePlaceholder":346},[174,680,682],{"class":120,"line":681},38,[174,683,684],{"class":315},"  \u002F* Opacity-only reveal keeps the animation off the layout path, which\n",[174,686,688],{"class":120,"line":687},39,[174,689,690],{"class":315},"     matters because the placement is recomputed during layout. *\u002F\n",[174,692,694,697,699,702],{"class":120,"line":693},40,[174,695,696],{"class":186},"  opacity",[174,698,335],{"class":179},[174,700,701],{"class":186},"0",[174,703,381],{"class":179},[174,705,707,710,713,716,719,722],{"class":120,"line":706},41,[174,708,709],{"class":186},"  transition",[174,711,712],{"class":179},": opacity ",[174,714,715],{"class":186},"0.15",[174,717,718],{"class":395},"s",[174,720,721],{"class":186}," ease",[174,723,381],{"class":179},[174,725,727],{"class":120,"line":726},42,[174,728,458],{"class":179},[174,730,732],{"class":120,"line":731},43,[174,733,347],{"emptyLinePlaceholder":346},[174,735,737,740,743,746],{"class":120,"line":736},44,[174,738,739],{"class":186},".tt__trigger:hover",[174,741,742],{"class":395}," +",[174,744,745],{"class":186}," .tt__bubble",[174,747,748],{"class":179},",\n",[174,750,752,755,757,759],{"class":120,"line":751},45,[174,753,754],{"class":186},".tt__trigger:focus-visible",[174,756,742],{"class":395},[174,758,745],{"class":186},[174,760,355],{"class":179},[174,762,764,766,768,770],{"class":120,"line":763},46,[174,765,696],{"class":186},[174,767,335],{"class":179},[174,769,414],{"class":186},[174,771,381],{"class":179},[174,773,775],{"class":120,"line":774},47,[174,776,458],{"class":179},[14,778,779,780,783,784,786,787,790,791,794,795,798],{},"The bubble is never removed from the box tree — it fades between ",[24,781,782],{},"opacity: 0"," and ",[24,785,414],{}," and stays in the layout. That is a deliberate choice for ",[24,788,789],{},"role=\"tooltip\"",": the element referenced by ",[24,792,793],{},"aria-describedby"," must remain in the accessibility tree for the reference to resolve, and ",[24,796,797],{},"display: none"," would take it out of that tree entirely, leaving the trigger with a dangling reference and no description.",[33,800,802],{"id":801},"the-technique-fallbacks-are-re-layouts-not-transforms","The technique: fallbacks are re-layouts, not transforms",[14,804,805,806,808],{},"The property doing the interesting work is ",[24,807,30],{},". It is worth being precise about what happens, because the mental model people import from JavaScript positioners is subtly wrong.",[14,810,811,812,816],{},"A library typically computes a position, measures the resulting rectangle against the viewport, and then ",[813,814,815],"em",{},"nudges"," — shifting the element by the overflow amount, or swapping a sign in the arithmetic. Anchor positioning does not nudge. The browser lays the element out with the primary placement, tests whether the resulting box overflows its inset-modified containing block, and if it does, throws that layout away and lays the element out again from scratch using the next candidate. Each candidate is a complete, independent placement.",[14,818,819,820,823],{},"That distinction has three practical consequences. First, a candidate can legitimately change more than direction: a ",[24,821,822],{},"@position-try"," rule may alter margins, sizing and alignment too, so \"flip to below\" and \"flip to below, and also become full width\" are both single candidates. Second, only one candidate ever applies at a time — you never end up in a blended state between two. Third, the last candidate in the list is the one used when nothing fits, so put your most tolerant placement last rather than assuming the browser will pick a least-bad option on its own.",[14,825,826,827,830,831,834,835,51],{},"The ",[24,828,829],{},"margin: 0.4rem"," shorthand pairs with this. Because each candidate is a fresh layout with a fresh notion of which side faces the anchor, a symmetric margin gives you the same visual gap in all four directions without writing four rules. A ",[24,832,833],{},"margin-block-end: 0.4rem"," would produce a gap above the trigger and none below it after a ",[24,836,837],{},"flip-block",[33,839,841],{"id":840},"getting-the-association-right","Getting the association right",[14,843,844],{},"Now the half that CSS cannot do. The rules are short and each one is load-bearing:",[14,846,847,851,852,855,856,859,860,863,864,51],{},[848,849,850],"strong",{},"The trigger must be genuinely focusable."," A ",[24,853,854],{},"\u003Cbutton>"," or a link. Not a ",[24,857,858],{},"\u003Cspan>"," with ",[24,861,862],{},"tabindex=\"0\""," and a click handler, which announces as generic text, and not an icon with no accessible name. If the trigger is icon-only, give it one: ",[24,865,866],{},"\u003Cbutton aria-label=\"Retention policy\">",[14,868,869,872,873,875,876,879,880,882],{},[848,870,871],{},"The tooltip must be referenced, not merely adjacent."," ",[24,874,793],{}," on the trigger pointing at the tooltip's ",[24,877,878],{},"id"," is what makes a screen reader read the bubble's text after the button's name. ",[24,881,789],{}," on the bubble tells assistive technology what kind of thing it is. Neither is implied by proximity.",[14,884,885,888,889,891,892,895,896,900],{},[848,886,887],{},"The tooltip must contain no interactive content."," This is the constraint that most often forces a different component. ",[24,890,789],{}," describes a passive hint; there is no reliable, standards-blessed way for a keyboard user to move focus ",[813,893,894],{},"into"," a tooltip. If your bubble needs a link or a button in it, it is not a tooltip — reach for a popover panel opened by click, which is what the ",[18,897,899],{"href":898},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling\u002F","popover attribute and CSS styling"," page builds.",[14,902,903,906,907,910,911,914,915,51],{},[848,904,905],{},"Hover and focus must both work, and the content must survive contact."," WCAG 1.4.13 requires content revealed on hover or focus to be dismissible, hoverable and persistent. The ",[24,908,909],{},":focus-visible"," selector above covers the keyboard reveal; the ",[24,912,913],{},"margin"," gap is small enough that pointer travel between trigger and bubble rarely drops the hover state, but if you widen the gap you need a transparent bridge to keep the hit area continuous. The full treatment of those three criteria, including the one that genuinely needs a keypress handler, is in ",[18,916,918],{"href":917},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips\u002F","accessible CSS-only tooltips",[14,920,921,924,925,928],{},[848,922,923],{},"Do not reuse one anchor name across a list."," Twenty toolbar buttons all declaring ",[24,926,927],{},"anchor-name: --tt"," will all resolve to the last one, and every tooltip in the toolbar will appear over the final button. Emit a per-instance name from your templating layer, or set it inline from a custom property:",[165,930,932],{"className":306,"code":931,"language":308,"meta":170,"style":170},".tt__trigger { anchor-name: var(--tt-name); }\n",[24,933,934],{"__ignoreMap":170},[174,935,936,938,940,943,945,948,951,955],{"class":120,"line":176},[174,937,352],{"class":186},[174,939,329],{"class":179},[174,941,942],{"class":186},"anchor-name",[174,944,335],{"class":179},[174,946,947],{"class":186},"var",[174,949,950],{"class":179},"(",[174,952,954],{"class":953},"soyes","--tt-name",[174,956,957],{"class":179},"); }\n",[165,959,961],{"className":167,"code":960,"language":169,"meta":170,"style":170},"\u003Cbutton class=\"tt__trigger\" style=\"--tt-name: --tt-3\" aria-describedby=\"tt-3\">…\u003C\u002Fbutton>\n",[24,962,963],{"__ignoreMap":170},[174,964,965,967,969,971,973,975,978,980,983,985,987,990,993,995],{"class":120,"line":176},[174,966,180],{"class":179},[174,968,206],{"class":183},[174,970,187],{"class":186},[174,972,190],{"class":179},[174,974,221],{"class":193},[174,976,977],{"class":186}," style",[174,979,190],{"class":179},[174,981,982],{"class":193},"\"--tt-name: --tt-3\"",[174,984,224],{"class":186},[174,986,190],{"class":179},[174,988,989],{"class":193},"\"tt-3\"",[174,991,992],{"class":179},">…\u003C\u002F",[174,994,206],{"class":183},[174,996,197],{"class":179},[33,998,1000],{"id":999},"variation-reduced-motion-and-a-stable-reading-position","Variation: reduced motion and a stable reading position",[14,1002,1003,1004,1007],{},"Two refinements matter for users who are sensitive to movement. The first is obvious: honour ",[24,1005,1006],{},"prefers-reduced-motion"," by dropping the fade to an instant swap. The second is less obvious and more useful — a tooltip that flips its side as the user scrolls is far more disruptive than one that simply disappears. Pinning the tooltip's visibility to the anchor's own visibility prevents both the pointing-at-nothing state and the mid-scroll flip.",[165,1009,1011],{"className":306,"code":1010,"language":308,"meta":170,"style":170},"@media (prefers-reduced-motion: reduce) {\n  .tt__bubble { transition: none; }\n}\n\n.tt__bubble {\n  \u002F* Stop painting the bubble once the trigger scrolls out of the scrollport\n     rather than pinning it to the edge with nothing to point at. *\u002F\n  position-visibility: anchors-visible;\n}\n",[24,1012,1013,1021,1037,1041,1045,1051,1056,1061,1069],{"__ignoreMap":170},[174,1014,1015,1018],{"class":120,"line":176},[174,1016,1017],{"class":395},"@media",[174,1019,1020],{"class":179}," (prefers-reduced-motion: reduce) {\n",[174,1022,1023,1026,1028,1031,1033,1035],{"class":120,"line":200},[174,1024,1025],{"class":186},"  .tt__bubble",[174,1027,329],{"class":179},[174,1029,1030],{"class":186},"transition",[174,1032,335],{"class":179},[174,1034,87],{"class":186},[174,1036,341],{"class":179},[174,1038,1039],{"class":120,"line":234},[174,1040,458],{"class":179},[174,1042,1043],{"class":120,"line":240},[174,1044,347],{"emptyLinePlaceholder":346},[174,1046,1047,1049],{"class":120,"line":250},[174,1048,469],{"class":186},[174,1050,355],{"class":179},[174,1052,1053],{"class":120,"line":281},[174,1054,1055],{"class":315},"  \u002F* Stop painting the bubble once the trigger scrolls out of the scrollport\n",[174,1057,1058],{"class":120,"line":287},[174,1059,1060],{"class":315},"     rather than pinning it to the edge with nothing to point at. *\u002F\n",[174,1062,1063,1066],{"class":120,"line":296},[174,1064,1065],{"class":186},"  position-visibility",[174,1067,1068],{"class":179},": anchors-visible;\n",[174,1070,1071],{"class":120,"line":384},[174,1072,458],{"class":179},[14,1074,1075,1076,1079,1080,783,1083,1086,1087,1090,1091,1094],{},"For right-to-left interfaces no extra work is required, and that is worth noticing rather than skipping past. Because the implementation uses ",[24,1077,1078],{},"position-area: block-start center"," and the logical flip keywords rather than ",[24,1081,1082],{},"top",[24,1084,1085],{},"left",", the placement mirrors automatically under ",[24,1088,1089],{},"direction: rtl",". Had the same tooltip been written with ",[24,1092,1093],{},"left: anchor(left)",", it would need a separate rule per writing mode.",[33,1096,1098],{"id":1097},"browser-support","Browser support",[14,1100,1101,1102,1104,1105,1108,1109,1111,1112,1114,1115,1118],{},"Anchor positioning ships in Chrome 125+, Edge 125+, Safari 26+ and Firefox 147+. The two properties this page leans on hardest arrived slightly later in Chromium: ",[24,1103,30],{}," in 128 and ",[24,1106,1107],{},"position-area"," in 129. Anything built on an older engine than that — which still includes a meaningful slice of embedded webviews — needs the fallback placement. Everything else on this page is universally supported: ",[24,1110,909],{}," (Chrome 86+, Edge 86+, Firefox 85+, Safari 15.4+), ",[24,1113,793],{},", and opacity transitions carry no caveats. Guard only the placement block with ",[24,1116,1117],{},"@supports (anchor-name: --x)"," and let the rest apply everywhere.",[33,1120,1122],{"id":1121},"faq","FAQ",[14,1124,1125,1128,1129,1131,1132,1134],{},[848,1126,1127],{},"Does anchor positioning make a tooltip accessible?","\nNo. It only changes where the box paints. The tooltip still needs a real focusable trigger, an ",[24,1130,793],{}," reference from that trigger to the tooltip's ",[24,1133,878],{},", and DOM order that places the tooltip next to its trigger.",[14,1136,1137,1147,1148,1150,1151,1153,1154,1157],{},[848,1138,1139,1140,1142,1143,1146],{},"Should the tooltip use ",[24,1141,789],{}," or the ",[24,1144,1145],{},"popover"," attribute?","\nUse ",[24,1149,789],{}," for a short descriptive hint revealed by hover and focus. The ",[24,1152,1145],{}," attribute is a better fit when the panel is opened by a deliberate click and contains interactive controls, because it brings light dismiss and ",[156,1155,1156],{},"Escape"," handling with it.",[14,1159,1160,1163,1164,1167],{},[848,1161,1162],{},"Why does my tooltip flip when there is clearly room?","\nThe overflow test runs against the inset-modified containing block, not the visible viewport. Large margins, a scrollbar gutter, or an ",[24,1165,1166],{},"inset"," declaration left over from a fallback stylesheet shrink that rectangle and make a fitting placement look like an overflow.",[14,1169,1170,1173,1174,1177],{},[848,1171,1172],{},"How do I keep the tooltip from following a trigger that has scrolled away?","\nSet ",[24,1175,1176],{},"position-visibility: anchors-visible"," on the tooltip. The browser then stops painting it once the anchor leaves the scrollport, instead of pinning it to the edge pointing at nothing.",[33,1179,1181],{"id":1180},"related","Related",[1183,1184,1185,1191,1197,1203,1209],"ul",{},[1186,1187,1188,1190],"li",{},[18,1189,21],{"href":20}," — the parent guide covering the full property set.",[1186,1192,1193,1196],{},[18,1194,1195],{"href":898},"Popover attribute and CSS styling"," — the right component when the panel holds interactive content.",[1186,1198,1199,1202],{},[18,1200,1201],{"href":49},"Anchor positioning fallbacks"," — the placement to ship underneath this one.",[1186,1204,1205,1208],{},[18,1206,1207],{"href":917},"Accessible CSS-only tooltips"," — cross-area: the WCAG 1.4.13 criteria in full.",[1186,1210,1211,1215],{},[18,1212,1214],{"href":1213},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fcreating-accessible-focus-indicators\u002F","Creating accessible focus indicators"," — cross-area: making the trigger's focus state visible enough.",[1217,1218,1219],"style",{},"html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}",{"title":170,"searchDepth":200,"depth":200,"links":1221},[1222,1223,1224,1225,1226,1227,1228,1229],{"id":35,"depth":200,"text":36},{"id":150,"depth":200,"text":151},{"id":801,"depth":200,"text":802},{"id":840,"depth":200,"text":841},{"id":999,"depth":200,"text":1000},{"id":1097,"depth":200,"text":1098},{"id":1121,"depth":200,"text":1122},{"id":1180,"depth":200,"text":1181},"Build a tooltip tethered with anchor-name and position-anchor that flips on viewport overflow via position-try-fallbacks, with correct ARIA association.","md",{"pageTitle":1233,"datePublished":1234,"dateModified":1234,"faq":1235},"Anchor-Positioned Tooltips That Flip","2026-07-20",[1236,1238,1241,1243],{"q":1127,"a":1237},"No. It only changes where the box paints. The tooltip still needs a real focusable trigger, an aria-describedby reference from that trigger to the tooltip's id, and DOM order that places the tooltip next to its trigger.",{"q":1239,"a":1240},"Should the tooltip use role=tooltip or the popover attribute?","Use role=tooltip for a short descriptive hint revealed by hover and focus. The popover attribute is a better fit when the panel is opened by a deliberate click and contains interactive controls, because it brings light dismiss and Escape handling with it.",{"q":1162,"a":1242},"The overflow test runs against the inset-modified containing block, not the visible viewport. Large margins, a scrollbar gutter, or an inset declaration left over from a fallback stylesheet shrink that rectangle and make a fitting placement look like an overflow.",{"q":1172,"a":1244},"Set position-visibility to anchors-visible on the tooltip. The browser then stops painting it once the anchor leaves the scrollport, instead of pinning it to the edge pointing at nothing.","\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips",{"title":5,"description":1230},"mastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips\u002Findex","Ip_LdtPTdl5HeuCon1xz_FnbRELTr083nV7LJWNDI0U",[1250,1253,1256,1259,1262,1265,1268,1271,1274,1277,1280,1283,1286,1289,1292,1295,1298,1301,1304,1307,1310,1313,1316,1319,1322,1325,1328,1331,1334,1337,1340,1343,1346,1349,1352,1355,1358,1361,1364,1367,1370,1373,1376,1379,1382,1385,1388,1391,1392,1395,1398,1401,1404,1407,1410,1413,1416,1419,1422,1425,1428,1431,1434,1437,1440,1443,1446,1449,1452,1455,1458,1461,1464,1467,1470,1473,1476,1479,1482,1485,1488,1491,1494,1497,1500,1503,1506,1509],{"path":1251,"title":1252},"\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":1254,"title":1255},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1257,"title":1258},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1260,"title":1261},"\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":1263,"title":1264},"\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":1266,"title":1267},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1269,"title":1270},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1272,"title":1273},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1275,"title":1276},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1278,"title":1279},"\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":1281,"title":1282},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":1284,"title":1285},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1287,"title":1288},"\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":1290,"title":1291},"\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":1293,"title":1294},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1296,"title":1297},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1299,"title":1300},"\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":1302,"title":1303},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1305,"title":1306},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1308,"title":1309},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1311,"title":1312},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1314,"title":1315},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1317,"title":1318},"\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":1320,"title":1321},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1323,"title":1324},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1326,"title":1327},"\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":1329,"title":1330},"\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":1332,"title":1333},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1335,"title":1336},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1338,"title":1339},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1341,"title":1342},"\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":1344,"title":1345},"\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":1347,"title":1348},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1350,"title":1351},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1353,"title":1354},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1356,"title":1357},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1359,"title":1360},"\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":1362,"title":1363},"\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":1365,"title":1366},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1368,"title":1369},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1371,"title":1372},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1374,"title":1375},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1377,"title":1378},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1380,"title":1381},"\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":1383,"title":1384},"\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":1386,"title":1387},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":1389,"title":1390},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":1245,"title":5},{"path":1393,"title":1394},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1396,"title":1397},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1399,"title":1400},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1402,"title":1403},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1405,"title":1406},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1408,"title":1409},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1411,"title":1412},"\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":1414,"title":1415},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1417,"title":1418},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1420,"title":1421},"\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":1423,"title":1424},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1426,"title":1427},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1429,"title":1430},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1432,"title":1433},"\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":1435,"title":1436},"\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":1438,"title":1439},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1441,"title":1442},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1444,"title":1445},"\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":1447,"title":1448},"\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":1450,"title":1451},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1453,"title":1454},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1456,"title":1457},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1459,"title":1460},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1462,"title":1463},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1465,"title":1466},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1468,"title":1469},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1471,"title":1472},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1474,"title":1475},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1477,"title":1478},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1480,"title":1481},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1483,"title":1484},"\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":1486,"title":1487},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1489,"title":1490},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":1492,"title":1493},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":1495,"title":1496},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":1498,"title":1499},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":1501,"title":1502},"\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":1504,"title":1505},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":1507,"title":1508},"\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":1510,"title":1511},"\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",1784566157143]