[{"data":1,"prerenderedAt":3396},["ShallowReactive",2],{"page-\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout":3,"content-all-pages":2837},{"id":4,"title":5,"body":6,"description":2817,"extension":2818,"meta":2819,"navigation":1023,"path":2833,"seo":2834,"stem":2835,"__hash__":2836},"content\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Findex.md","Viewport Units & Mobile Layout: Designing for the Screen You Actually Get",{"type":7,"value":8,"toc":2795},"minimark",[9,13,28,34,76,79,84,106,121,225,252,257,260,327,336,340,346,353,355,359,569,583,585,589,593,636,644,648,749,754,758,921,927,931,1089,1093,1180,1189,1191,1195,1198,1461,2116,2138,2140,2144,2162,2182,2192,2201,2217,2219,2223,2238,2249,2264,2274,2284,2365,2367,2371,2446,2448,2452,2575,2580,2582,2586,2685,2687,2691,2697,2709,2721,2742,2751,2755,2791],[10,11,5],"h1",{"id":12},"viewport-units-mobile-layout-designing-for-the-screen-you-actually-get",[14,15,16,17,22,23,27],"p",{},"Desktop CSS grew up with a simple model of the viewport: a rectangle the size of the browser window, stable while the page scrolls. Phones broke every part of that model. The visible area changes as toolbars slide away, the on-screen keyboard covers half the page without resizing it, pinch-zoom shows a small part of the layout, and screens have notches, rounded corners and gesture bars. This guide, part of ",[18,19,21],"a",{"href":20},"\u002Fmastering-container-queries-responsive-layouts\u002F","Mastering Container Queries & Responsive Layouts",", explains the mobile viewport as the browser actually implements it and the CSS features built to work with it — the new viewport units, safe-area insets, edge-to-edge sections — and when to stop measuring the viewport altogether and use ",[18,24,26],{"href":25},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-units-cqi-cqb-explained\u002F","container query units"," instead.",[14,29,30],{},[31,32,33],"strong",{},"Prerequisites — this guide assumes you can already:",[35,36,37,46,61,68],"ul",{},[38,39,40,41,45],"li",{},"Write a viewport meta tag and explain what ",[42,43,44],"code",{},"width=device-width"," does.",[38,47,48,49,52,53,56,57,60],{},"Use ",[42,50,51],{},"clamp()",", ",[42,54,55],{},"min()"," and ",[42,58,59],{},"max()"," in length values.",[38,62,63,64,67],{},"Build a basic grid layout with ",[42,65,66],{},"grid-template-columns",".",[38,69,70,71,75],{},"Distinguish a size container from an inline-size container (see ",[18,72,74],{"href":73},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size\u002F","container-type: size vs inline-size",").",[77,78],"hr",{},[80,81,83],"h2",{"id":82},"the-core-concept-two-viewports-three-heights","The Core Concept: Two Viewports, Three Heights",[14,85,86,87,90,91,94,95,52,98,101,102,105],{},"Browsers maintain two viewports. The ",[31,88,89],{},"layout viewport"," is the rectangle CSS layout is computed against: the initial containing block, the reference for ",[42,92,93],{},"position: fixed",", and the box that ",[42,96,97],{},"vw",[42,99,100],{},"vh"," and their relatives measure. The ",[31,103,104],{},"visual viewport"," is the portion of the page actually on screen right now. On desktop they are the same rectangle. On mobile they diverge whenever the user pinch-zooms (the visual viewport shrinks to a region of the layout) or opens the on-screen keyboard (the visual viewport shrinks, the layout viewport by default does not).",[14,107,108,109,112,113,116,117,120],{},"The layout viewport itself changes height as mobile toolbars retract and reappear. The CSS Values specification names the three heights that matter: the ",[31,110,111],{},"small"," viewport with all toolbars shown, the ",[31,114,115],{},"large"," viewport with them hidden, and the ",[31,118,119],{},"dynamic"," viewport, which is whichever is current.",[122,123,129,130,129,134,129,138,129,146,129,157,129,163,129,172,129,175,129,180,129,187,129,193,129,197,129,201,129,205,129,209,129,213,129,217,129,221],"svg",{"viewBox":124,"role":125,"ariaLabel":126,"xmlns":127,"style":128},"0 0 720 340","img","Layered diagram of the page, the layout viewport and the visual viewport on a phone, with the keyboard covering part of the visual viewport","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[131,132,133],"title",{},"Page, layout viewport and visual viewport",[135,136,137],"desc",{},"The full page is a tall outline. Inside it the layout viewport is the rectangle CSS measures, sized between the small and large viewport heights. The visual viewport is the part on screen; when the keyboard opens it shrinks while the layout viewport stays the same.",[139,140,145],"text",{"textAnchor":141,"x":142,"y":143,"style":144},"middle","360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","What CSS measures versus what the user sees",[147,148],"path",{"d":149,"fill":150,"stroke":151,"strokeWidth":152,"strokeDashArray":153,"opacity":156},"M60 46 H260 V320 H60 Z","none","currentColor","1.5",[154,155],"6","4","0.6",[139,158,162],{"textAnchor":141,"x":159,"y":160,"style":161},"160","66","text-anchor:middle;fill:currentColor;font:12px sans-serif","the whole page",[164,165],"rect",{"x":166,"y":167,"width":168,"height":169,"rx":154,"fill":170,"opacity":171},"76","90","168","170","#7aa2ff","0.24",[139,173,89],{"textAnchor":141,"x":159,"y":159,"style":174},"text-anchor:middle;fill:currentColor;font:600 13px sans-serif",[139,176,179],{"textAnchor":141,"x":159,"y":177,"style":178},"182","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","vw · svh · dvh",[164,181],{"x":182,"y":183,"width":142,"height":184,"rx":185,"fill":150,"stroke":151,"strokeWidth":152,"opacity":186},"330","60","118","10","0.55",[139,188,192],{"textAnchor":141,"x":189,"y":190,"style":191},"510","86","text-anchor:middle;fill:currentColor;font:700 13px sans-serif","Layout viewport",[139,194,196],{"textAnchor":141,"x":189,"y":195,"style":161},"110","what layout, fixed positioning",[139,198,200],{"textAnchor":141,"x":189,"y":199,"style":161},"130","and viewport units measure;",[139,202,204],{"textAnchor":141,"x":189,"y":203,"style":161},"150","height varies with toolbars",[164,206],{"x":182,"y":207,"width":142,"height":184,"rx":185,"fill":170,"opacity":208},"196","0.16",[139,210,212],{"textAnchor":141,"x":189,"y":211,"style":191},"222","Visual viewport",[139,214,216],{"textAnchor":141,"x":189,"y":215,"style":161},"246","what is on screen right now;",[139,218,220],{"textAnchor":141,"x":189,"y":219,"style":161},"266","shrinks for pinch-zoom and,",[139,222,224],{"textAnchor":141,"x":189,"y":223,"style":161},"286","by default, the keyboard",[14,226,227,228,232,233,237,238,242,243,246,247,251],{},"Every mobile layout problem in this section maps onto that picture. ",[18,229,231],{"href":230},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fdvh-svh-lvh-mobile-viewport-units\u002F","dvh, svh and lvh"," are the three heights of the layout viewport. ",[18,234,236],{"href":235},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fsafe-area-insets-for-notched-screens\u002F","Safe Area Insets for Notched Screens"," describes the parts of the layout viewport that hardware obscures. ",[18,239,241],{"href":240},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Ffull-bleed-sections-in-constrained-layouts\u002F","Full-Bleed Sections in Constrained Layouts"," deals with the width of the layout viewport and why ",[42,244,245],{},"100vw"," includes a scrollbar. And ",[18,248,250],{"href":249},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fviewport-units-vs-container-units\u002F","Viewport Units vs Container Units"," covers the many cases where the viewport is simply the wrong reference box.",[253,254,256],"h3",{"id":255},"what-happens-during-one-scroll","What happens during one scroll",[14,258,259],{},"It helps to watch the three heights over the course of a single gesture. The page loads with toolbars visible. The user scrolls down; partway through, the browser slides its toolbars away. The user scrolls back up a little; the toolbars return. The small and large heights never change during any of this — they are properties of the device and browser, not of the moment. Only the dynamic height moves.",[122,261,129,264,129,267,129,270,129,273,129,278,129,281,129,287,129,291,129,297,129,301,129,305,129,308,129,312,129,317,129,321],{"viewBox":262,"role":125,"ariaLabel":263,"xmlns":127,"style":128},"0 0 720 300","Line chart of svh, lvh and dvh over one scroll gesture, with dvh stepping between the two constants as the toolbar hides and returns",[131,265,266],{},"The three heights across a scroll",[135,268,269],{},"Two horizontal lines mark the constant small and large viewport heights. The dynamic height starts on the small line, rises to the large line when the toolbar hides mid-scroll, and falls back to the small line when the user scrolls up and the toolbar returns.",[139,271,272],{"textAnchor":141,"x":142,"y":143,"style":144},"Only dvh moves while the user scrolls",[274,275],"line",{"x1":167,"y1":276,"x2":277,"y2":276,"stroke":151,"strokeWidth":152,"opacity":156},"250","680",[274,279],{"x1":167,"y1":280,"x2":167,"y2":276,"stroke":151,"strokeWidth":152,"opacity":156},"50",[139,282,286],{"textAnchor":283,"x":277,"y":284,"style":285},"end","272","text-anchor:end;fill:currentColor;font:12px sans-serif","time during one scroll",[274,288],{"x1":167,"y1":167,"x2":277,"y2":167,"stroke":151,"strokeWidth":152,"strokeDashArray":289,"opacity":290},[154,155],"0.7",[139,292,296],{"textAnchor":283,"x":293,"y":294,"style":295},"84","94","text-anchor:end;fill:currentColor;font:12px ui-monospace,monospace","lvh",[274,298],{"x1":167,"y1":299,"x2":277,"y2":299,"stroke":151,"strokeWidth":152,"strokeDashArray":300,"opacity":290},"190",[154,155],[139,302,304],{"textAnchor":283,"x":293,"y":303,"style":295},"194","svh",[147,306],{"d":307,"fill":150,"stroke":170,"strokeWidth":155},"M90 190 H250 L300 90 H480 L530 190 H680",[139,309,311],{"textAnchor":141,"x":169,"y":310,"style":161},"178","loaded, UI shown",[139,313,316],{"textAnchor":141,"x":314,"y":315,"style":161},"390","78","UI hidden",[139,318,320],{"textAnchor":141,"x":319,"y":310,"style":161},"605","UI back",[139,322,326],{"textAnchor":141,"x":323,"y":324,"style":325},"275","230","text-anchor:middle;fill:currentColor;font:600 12px ui-monospace,monospace","dvh",[14,328,329,330,332,333,335],{},"That chart is the whole argument for choosing units by element type. Anything drawn with the dashed lines — ",[42,331,304],{}," or ",[42,334,296],{}," — is laid out once and stays put. Anything drawn with the solid line is laid out again at each step. For an overlay that must match the screen, re-layout is the requirement; for a hero in the document flow, it is a layout shift that the user sees as content jumping under their finger.",[253,337,339],{"id":338},"where-container-units-take-over","Where container units take over",[14,341,342,343,345],{},"Viewport units answer questions about the screen. Many sizing questions that used to be answered with viewport units were never really about the screen: they were about the component, and the viewport was used because it was the only box CSS could measure. A card's heading scaled in ",[42,344,97],{}," is correct only while the card is roughly as wide as the viewport, which on a multi-column desktop layout it never is.",[14,347,348,349,352],{},"Container query units measure the nearest size container instead, and they fall back to the small viewport when no container exists, so they are strictly more portable for component-level sizing. The practical split is simple enough to apply during code review: if moving the component into a sidebar should change the value, it belongs to the component and should use ",[42,350,351],{},"cqi","; if it should not, it belongs to the screen and a viewport unit is right. Heights are almost always screen-owned — nothing about a card's width says how tall an overlay may be — which is why the viewport height units remain essential even in a fully container-query-driven design system.",[77,354],{},[80,356,358],{"id":357},"syntax-and-parameters","Syntax and Parameters",[360,361,362,378],"table",{},[363,364,365],"thead",{},[366,367,368,372,375],"tr",{},[369,370,371],"th",{},"Token",[369,373,374],{},"Accepted values",[369,376,377],{},"Default \u002F notes",[379,380,381,408,430,452,474,491,522,546],"tbody",{},[366,382,383,396,402],{},[384,385,386,52,388,52,390,52,393],"td",{},[42,387,97],{},[42,389,100],{},[42,391,392],{},"vi",[42,394,395],{},"vb",[384,397,398,401],{},[42,399,400],{},"\u003Cnumber>"," unit",[384,403,404,405,407],{},"Classic units; on mobile, ",[42,406,100],{}," behaves as the large viewport",[366,409,410,423,427],{},[384,411,412,52,415,52,417,52,420],{},[42,413,414],{},"svw",[42,416,304],{},[42,418,419],{},"svi",[42,421,422],{},"svb",[384,424,425,401],{},[42,426,400],{},[384,428,429],{},"Small viewport: all toolbars shown",[366,431,432,445,449],{},[384,433,434,52,437,52,439,52,442],{},[42,435,436],{},"lvw",[42,438,296],{},[42,440,441],{},"lvi",[42,443,444],{},"lvb",[384,446,447,401],{},[42,448,400],{},[384,450,451],{},"Large viewport: toolbars hidden",[366,453,454,467,471],{},[384,455,456,52,459,52,461,52,464],{},[42,457,458],{},"dvw",[42,460,326],{},[42,462,463],{},"dvi",[42,465,466],{},"dvb",[384,468,469,401],{},[42,470,400],{},[384,472,473],{},"Dynamic: whichever is current",[366,475,476,484,488],{},[384,477,478,52,481],{},[42,479,480],{},"*vmin",[42,482,483],{},"*vmax",[384,485,486,401],{},[42,487,400],{},[384,489,490],{},"Smaller \u002F larger of the two axes, for each family",[366,492,493,498,513],{},[384,494,495],{},[42,496,497],{},"env(safe-area-inset-*)",[384,499,500,52,503,52,506,52,509,512],{},[42,501,502],{},"top",[42,504,505],{},"right",[42,507,508],{},"bottom",[42,510,511],{},"left",", optional fallback",[384,514,515,518,519],{},[42,516,517],{},"0px"," unless ",[42,520,521],{},"viewport-fit=cover",[366,523,524,530,541],{},[384,525,526,529],{},[42,527,528],{},"viewport-fit"," (meta)",[384,531,532,52,535,52,538],{},[42,533,534],{},"auto",[42,536,537],{},"contain",[42,539,540],{},"cover",[384,542,543,545],{},[42,544,534],{}," letterboxes inside the safe area",[366,547,548,553,564],{},[384,549,550,529],{},[42,551,552],{},"interactive-widget",[384,554,555,52,558,52,561],{},[42,556,557],{},"resizes-visual",[42,559,560],{},"resizes-content",[42,562,563],{},"overlays-content",[384,565,566,567],{},"Browser default is usually ",[42,568,557],{},[14,570,571,572,52,574,576,577,579,580,582],{},"The logical variants (",[42,573,392],{},[42,575,395],{}," and their prefixed forms) follow the writing mode: in horizontal text ",[42,578,392],{}," is width and ",[42,581,395],{}," is height, and in vertical writing modes they swap. Use them in components that may be rendered in vertical scripts.",[77,584],{},[80,586,588],{"id":587},"step-by-step-implementation-a-mobile-ready-landing-page","Step-by-Step Implementation: A Mobile-Ready Landing Page",[253,590,592],{"id":591},"step-1-the-viewport-meta-tag","Step 1: the viewport meta tag",[594,595,600],"pre",{"className":596,"code":597,"language":598,"meta":599,"style":599},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n","html","",[42,601,602],{"__ignoreMap":599},[603,604,606,610,614,618,621,625,628,630,633],"span",{"class":274,"line":605},1,[603,607,609],{"class":608},"suds8","\u003C",[603,611,613],{"class":612},"sne4z","meta",[603,615,617],{"class":616},"s-5SL"," name",[603,619,620],{"class":608},"=",[603,622,624],{"class":623},"sT6z2","\"viewport\"",[603,626,627],{"class":616}," content",[603,629,620],{"class":608},[603,631,632],{"class":623},"\"width=device-width, initial-scale=1, viewport-fit=cover\"",[603,634,635],{"class":608},">\n",[14,637,638,640,641,643],{},[42,639,44],{}," makes the layout viewport match the device width in CSS pixels. ",[42,642,521],{}," extends drawing under notches and indicators, which is only safe once step 4 is in place.",[253,645,647],{"id":646},"step-2-a-hero-that-fits-on-load","Step 2: a hero that fits on load",[594,649,653],{"className":650,"code":651,"language":652,"meta":599,"style":599},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast",".hero {\n  min-height: 100vh;       \u002F* fallback *\u002F\n  min-height: 100svh;      \u002F* never taller than the visible area on load *\u002F\n  display: grid;\n  align-content: end;\n  padding: 1.5rem;\n}\n","css",[42,654,655,663,685,702,716,728,743],{"__ignoreMap":599},[603,656,657,660],{"class":274,"line":605},[603,658,659],{"class":616},".hero",[603,661,662],{"class":608}," {\n",[603,664,666,669,672,675,678,681],{"class":274,"line":665},2,[603,667,668],{"class":616},"  min-height",[603,670,671],{"class":608},": ",[603,673,674],{"class":616},"100",[603,676,100],{"class":677},"sHUrx",[603,679,680],{"class":608},";       ",[603,682,684],{"class":683},"sLBg1","\u002F* fallback *\u002F\n",[603,686,688,690,692,694,696,699],{"class":274,"line":687},3,[603,689,668],{"class":616},[603,691,671],{"class":608},[603,693,674],{"class":616},[603,695,304],{"class":677},[603,697,698],{"class":608},";      ",[603,700,701],{"class":683},"\u002F* never taller than the visible area on load *\u002F\n",[603,703,705,708,710,713],{"class":274,"line":704},4,[603,706,707],{"class":616},"  display",[603,709,671],{"class":608},[603,711,712],{"class":616},"grid",[603,714,715],{"class":608},";\n",[603,717,719,722,724,726],{"class":274,"line":718},5,[603,720,721],{"class":616},"  align-content",[603,723,671],{"class":608},[603,725,283],{"class":616},[603,727,715],{"class":608},[603,729,731,734,736,738,741],{"class":274,"line":730},6,[603,732,733],{"class":616},"  padding",[603,735,671],{"class":608},[603,737,152],{"class":616},[603,739,740],{"class":677},"rem",[603,742,715],{"class":608},[603,744,746],{"class":274,"line":745},7,[603,747,748],{"class":608},"}\n",[14,750,751,753],{},[42,752,304],{}," is stable during scrolling, so the hero never jumps as the toolbar retracts.",[253,755,757],{"id":756},"step-3-a-full-bleed-image-inside-a-reading-column","Step 3: a full-bleed image inside a reading column",[594,759,761],{"className":650,"code":760,"language":652,"meta":599,"style":599},".page {\n  display: grid;\n  grid-template-columns:\n    [full-start] minmax(1rem, 1fr)\n    [content-start] min(65ch, 100% - 2rem)\n    [content-end] minmax(1rem, 1fr)\n    [full-end];\n}\n.page > * { grid-column: content; }\n.page > .full-bleed { grid-column: full; }\n",[42,762,763,770,780,788,814,848,869,874,879,904],{"__ignoreMap":599},[603,764,765,768],{"class":274,"line":605},[603,766,767],{"class":616},".page",[603,769,662],{"class":608},[603,771,772,774,776,778],{"class":274,"line":665},[603,773,707],{"class":616},[603,775,671],{"class":608},[603,777,712],{"class":616},[603,779,715],{"class":608},[603,781,782,785],{"class":274,"line":687},[603,783,784],{"class":616},"  grid-template-columns",[603,786,787],{"class":608},":\n",[603,789,790,793,796,799,802,804,806,808,811],{"class":274,"line":704},[603,791,792],{"class":608},"    [full-start] ",[603,794,795],{"class":616},"minmax",[603,797,798],{"class":608},"(",[603,800,801],{"class":616},"1",[603,803,740],{"class":677},[603,805,52],{"class":608},[603,807,801],{"class":616},[603,809,810],{"class":677},"fr",[603,812,813],{"class":608},")\n",[603,815,816,819,822,824,827,830,832,834,837,841,844,846],{"class":274,"line":718},[603,817,818],{"class":608},"    [content-start] ",[603,820,821],{"class":616},"min",[603,823,798],{"class":608},[603,825,826],{"class":616},"65",[603,828,829],{"class":677},"ch",[603,831,52],{"class":608},[603,833,674],{"class":616},[603,835,836],{"class":677},"%",[603,838,840],{"class":839},"soyes"," -",[603,842,843],{"class":616}," 2",[603,845,740],{"class":677},[603,847,813],{"class":608},[603,849,850,853,855,857,859,861,863,865,867],{"class":274,"line":730},[603,851,852],{"class":608},"    [content-end] ",[603,854,795],{"class":616},[603,856,798],{"class":608},[603,858,801],{"class":616},[603,860,740],{"class":677},[603,862,52],{"class":608},[603,864,801],{"class":616},[603,866,810],{"class":677},[603,868,813],{"class":608},[603,870,871],{"class":274,"line":745},[603,872,873],{"class":608},"    [full-end];\n",[603,875,877],{"class":274,"line":876},8,[603,878,748],{"class":608},[603,880,882,884,887,890,893,896,898,901],{"class":274,"line":881},9,[603,883,767],{"class":616},[603,885,886],{"class":677}," >",[603,888,889],{"class":612}," *",[603,891,892],{"class":608}," { ",[603,894,895],{"class":616},"grid-column",[603,897,671],{"class":608},[603,899,900],{"class":616},"content",[603,902,903],{"class":608},"; }\n",[603,905,907,909,911,914,916,918],{"class":274,"line":906},10,[603,908,767],{"class":616},[603,910,886],{"class":677},[603,912,913],{"class":616}," .full-bleed",[603,915,892],{"class":608},[603,917,895],{"class":616},[603,919,920],{"class":608},": full; }\n",[14,922,923,924,926],{},"No ",[42,925,245],{}," means no scrollbar overhang on desktop platforms.",[253,928,930],{"id":929},"step-4-respect-the-safe-areas","Step 4: respect the safe areas",[594,932,934],{"className":650,"code":933,"language":652,"meta":599,"style":599},".page > * {\n  padding-inline: max(0px, env(safe-area-inset-left)) max(0px, env(safe-area-inset-right));\n}\n.page > .full-bleed { padding-inline: 0; }   \u002F* images may run under the notch *\u002F\n\n.bottom-bar {\n  position: fixed;\n  inset: auto 0 0 0;\n  padding-bottom: max(0.75rem, env(safe-area-inset-bottom));\n}\n",[42,935,936,946,992,996,1019,1025,1032,1044,1062,1085],{"__ignoreMap":599},[603,937,938,940,942,944],{"class":274,"line":605},[603,939,767],{"class":616},[603,941,886],{"class":677},[603,943,889],{"class":612},[603,945,662],{"class":608},[603,947,948,951,953,956,958,961,964,966,969,972,974,977,979,981,984,986,989],{"class":274,"line":665},[603,949,950],{"class":616},"  padding-inline",[603,952,671],{"class":608},[603,954,955],{"class":616},"max",[603,957,798],{"class":608},[603,959,960],{"class":616},"0",[603,962,963],{"class":677},"px",[603,965,52],{"class":608},[603,967,968],{"class":839},"env(safe-area-inset-left",[603,970,971],{"class":608},")) ",[603,973,955],{"class":616},[603,975,976],{"class":608},"(0",[603,978,963],{"class":616},[603,980,52],{"class":608},[603,982,983],{"class":616},"env",[603,985,798],{"class":608},[603,987,988],{"class":616},"safe-area-inset-right",[603,990,991],{"class":608},"));\n",[603,993,994],{"class":274,"line":687},[603,995,748],{"class":608},[603,997,998,1000,1002,1004,1006,1009,1011,1013,1016],{"class":274,"line":704},[603,999,767],{"class":616},[603,1001,886],{"class":677},[603,1003,913],{"class":616},[603,1005,892],{"class":608},[603,1007,1008],{"class":616},"padding-inline",[603,1010,671],{"class":608},[603,1012,960],{"class":616},[603,1014,1015],{"class":608},"; }   ",[603,1017,1018],{"class":683},"\u002F* images may run under the notch *\u002F\n",[603,1020,1021],{"class":274,"line":718},[603,1022,1024],{"emptyLinePlaceholder":1023},true,"\n",[603,1026,1027,1030],{"class":274,"line":730},[603,1028,1029],{"class":616},".bottom-bar",[603,1031,662],{"class":608},[603,1033,1034,1037,1039,1042],{"class":274,"line":745},[603,1035,1036],{"class":616},"  position",[603,1038,671],{"class":608},[603,1040,1041],{"class":616},"fixed",[603,1043,715],{"class":608},[603,1045,1046,1049,1051,1053,1056,1058,1060],{"class":274,"line":876},[603,1047,1048],{"class":616},"  inset",[603,1050,671],{"class":608},[603,1052,534],{"class":616},[603,1054,1055],{"class":616}," 0",[603,1057,1055],{"class":616},[603,1059,1055],{"class":616},[603,1061,715],{"class":608},[603,1063,1064,1067,1069,1071,1073,1076,1078,1080,1083],{"class":274,"line":881},[603,1065,1066],{"class":616},"  padding-bottom",[603,1068,671],{"class":608},[603,1070,955],{"class":616},[603,1072,798],{"class":608},[603,1074,1075],{"class":616},"0.75",[603,1077,740],{"class":677},[603,1079,52],{"class":608},[603,1081,1082],{"class":839},"env(safe-area-inset-bottom",[603,1084,991],{"class":608},[603,1086,1087],{"class":274,"line":906},[603,1088,748],{"class":608},[253,1090,1092],{"id":1091},"step-5-a-sheet-that-always-fits","Step 5: a sheet that always fits",[594,1094,1096],{"className":650,"code":1095,"language":652,"meta":599,"style":599},".sheet {\n  position: fixed;\n  inset: 0;\n  height: 100vh;\n  height: 100dvh;          \u002F* matches the visible area as the toolbar moves *\u002F\n  overflow: auto;\n  overscroll-behavior: contain;\n}\n",[42,1097,1098,1105,1115,1125,1138,1154,1165,1176],{"__ignoreMap":599},[603,1099,1100,1103],{"class":274,"line":605},[603,1101,1102],{"class":616},".sheet",[603,1104,662],{"class":608},[603,1106,1107,1109,1111,1113],{"class":274,"line":665},[603,1108,1036],{"class":616},[603,1110,671],{"class":608},[603,1112,1041],{"class":616},[603,1114,715],{"class":608},[603,1116,1117,1119,1121,1123],{"class":274,"line":687},[603,1118,1048],{"class":616},[603,1120,671],{"class":608},[603,1122,960],{"class":616},[603,1124,715],{"class":608},[603,1126,1127,1130,1132,1134,1136],{"class":274,"line":704},[603,1128,1129],{"class":616},"  height",[603,1131,671],{"class":608},[603,1133,674],{"class":616},[603,1135,100],{"class":677},[603,1137,715],{"class":608},[603,1139,1140,1142,1144,1146,1148,1151],{"class":274,"line":718},[603,1141,1129],{"class":616},[603,1143,671],{"class":608},[603,1145,674],{"class":616},[603,1147,326],{"class":677},[603,1149,1150],{"class":608},";          ",[603,1152,1153],{"class":683},"\u002F* matches the visible area as the toolbar moves *\u002F\n",[603,1155,1156,1159,1161,1163],{"class":274,"line":730},[603,1157,1158],{"class":616},"  overflow",[603,1160,671],{"class":608},[603,1162,534],{"class":616},[603,1164,715],{"class":608},[603,1166,1167,1170,1172,1174],{"class":274,"line":745},[603,1168,1169],{"class":616},"  overscroll-behavior",[603,1171,671],{"class":608},[603,1173,537],{"class":616},[603,1175,715],{"class":608},[603,1177,1178],{"class":274,"line":876},[603,1179,748],{"class":608},[14,1181,1182,1183,1185,1186,1188],{},"Each step uses the unit whose failure mode is acceptable for that element: stable ",[42,1184,304],{}," for in-flow content, exact ",[42,1187,326],{}," for an out-of-flow overlay, and no viewport width at all for the full-bleed image.",[77,1190],{},[80,1192,1194],{"id":1193},"annotated-production-example-a-bottom-sheet-with-a-composer","Annotated Production Example: A Bottom Sheet With a Composer",[14,1196,1197],{},"A bottom sheet with a text field is the hardest mobile layout to get right, because it combines a dynamic height, a keyboard, a home indicator and a scrolling body. The component below handles all four.",[594,1199,1201],{"className":596,"code":1200,"language":598,"meta":599,"style":599},"\u003C!-- In the head: allow the layout viewport to shrink for the keyboard. -->\n\u003Cmeta name=\"viewport\"\n      content=\"width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content\">\n\n\u003Csection class=\"sheet\" aria-label=\"Comments\">\n  \u003Cheader class=\"sheet__header\">\u003Ch2>Comments\u003C\u002Fh2>\u003C\u002Fheader>\n  \u003Cdiv class=\"sheet__body\" tabindex=\"0\">\n    \u003Cp>First comment…\u003C\u002Fp>\n  \u003C\u002Fdiv>\n  \u003Cform class=\"sheet__composer\">\n    \u003Clabel class=\"visually-hidden\" for=\"c\">Add a comment\u003C\u002Flabel>\n    \u003Cinput id=\"c\" name=\"comment\" autocomplete=\"off\">\n    \u003Cbutton type=\"submit\">Post\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Fsection>\n",[42,1202,1203,1208,1221,1233,1237,1262,1294,1318,1332,1341,1357,1387,1419,1442,1451],{"__ignoreMap":599},[603,1204,1205],{"class":274,"line":605},[603,1206,1207],{"class":683},"\u003C!-- In the head: allow the layout viewport to shrink for the keyboard. -->\n",[603,1209,1210,1212,1214,1216,1218],{"class":274,"line":665},[603,1211,609],{"class":608},[603,1213,613],{"class":612},[603,1215,617],{"class":616},[603,1217,620],{"class":608},[603,1219,1220],{"class":623},"\"viewport\"\n",[603,1222,1223,1226,1228,1231],{"class":274,"line":687},[603,1224,1225],{"class":616},"      content",[603,1227,620],{"class":608},[603,1229,1230],{"class":623},"\"width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content\"",[603,1232,635],{"class":608},[603,1234,1235],{"class":274,"line":704},[603,1236,1024],{"emptyLinePlaceholder":1023},[603,1238,1239,1241,1244,1247,1249,1252,1255,1257,1260],{"class":274,"line":718},[603,1240,609],{"class":608},[603,1242,1243],{"class":612},"section",[603,1245,1246],{"class":616}," class",[603,1248,620],{"class":608},[603,1250,1251],{"class":623},"\"sheet\"",[603,1253,1254],{"class":616}," aria-label",[603,1256,620],{"class":608},[603,1258,1259],{"class":623},"\"Comments\"",[603,1261,635],{"class":608},[603,1263,1264,1267,1270,1272,1274,1277,1280,1282,1285,1287,1290,1292],{"class":274,"line":730},[603,1265,1266],{"class":608},"  \u003C",[603,1268,1269],{"class":612},"header",[603,1271,1246],{"class":616},[603,1273,620],{"class":608},[603,1275,1276],{"class":623},"\"sheet__header\"",[603,1278,1279],{"class":608},">\u003C",[603,1281,80],{"class":612},[603,1283,1284],{"class":608},">Comments\u003C\u002F",[603,1286,80],{"class":612},[603,1288,1289],{"class":608},">\u003C\u002F",[603,1291,1269],{"class":612},[603,1293,635],{"class":608},[603,1295,1296,1298,1301,1303,1305,1308,1311,1313,1316],{"class":274,"line":745},[603,1297,1266],{"class":608},[603,1299,1300],{"class":612},"div",[603,1302,1246],{"class":616},[603,1304,620],{"class":608},[603,1306,1307],{"class":623},"\"sheet__body\"",[603,1309,1310],{"class":616}," tabindex",[603,1312,620],{"class":608},[603,1314,1315],{"class":623},"\"0\"",[603,1317,635],{"class":608},[603,1319,1320,1323,1325,1328,1330],{"class":274,"line":876},[603,1321,1322],{"class":608},"    \u003C",[603,1324,14],{"class":612},[603,1326,1327],{"class":608},">First comment…\u003C\u002F",[603,1329,14],{"class":612},[603,1331,635],{"class":608},[603,1333,1334,1337,1339],{"class":274,"line":881},[603,1335,1336],{"class":608},"  \u003C\u002F",[603,1338,1300],{"class":612},[603,1340,635],{"class":608},[603,1342,1343,1345,1348,1350,1352,1355],{"class":274,"line":906},[603,1344,1266],{"class":608},[603,1346,1347],{"class":612},"form",[603,1349,1246],{"class":616},[603,1351,620],{"class":608},[603,1353,1354],{"class":623},"\"sheet__composer\"",[603,1356,635],{"class":608},[603,1358,1360,1362,1365,1367,1369,1372,1375,1377,1380,1383,1385],{"class":274,"line":1359},11,[603,1361,1322],{"class":608},[603,1363,1364],{"class":612},"label",[603,1366,1246],{"class":616},[603,1368,620],{"class":608},[603,1370,1371],{"class":623},"\"visually-hidden\"",[603,1373,1374],{"class":616}," for",[603,1376,620],{"class":608},[603,1378,1379],{"class":623},"\"c\"",[603,1381,1382],{"class":608},">Add a comment\u003C\u002F",[603,1384,1364],{"class":612},[603,1386,635],{"class":608},[603,1388,1390,1392,1395,1398,1400,1402,1404,1406,1409,1412,1414,1417],{"class":274,"line":1389},12,[603,1391,1322],{"class":608},[603,1393,1394],{"class":612},"input",[603,1396,1397],{"class":616}," id",[603,1399,620],{"class":608},[603,1401,1379],{"class":623},[603,1403,617],{"class":616},[603,1405,620],{"class":608},[603,1407,1408],{"class":623},"\"comment\"",[603,1410,1411],{"class":616}," autocomplete",[603,1413,620],{"class":608},[603,1415,1416],{"class":623},"\"off\"",[603,1418,635],{"class":608},[603,1420,1422,1424,1427,1430,1432,1435,1438,1440],{"class":274,"line":1421},13,[603,1423,1322],{"class":608},[603,1425,1426],{"class":612},"button",[603,1428,1429],{"class":616}," type",[603,1431,620],{"class":608},[603,1433,1434],{"class":623},"\"submit\"",[603,1436,1437],{"class":608},">Post\u003C\u002F",[603,1439,1426],{"class":612},[603,1441,635],{"class":608},[603,1443,1445,1447,1449],{"class":274,"line":1444},14,[603,1446,1336],{"class":608},[603,1448,1347],{"class":612},[603,1450,635],{"class":608},[603,1452,1454,1457,1459],{"class":274,"line":1453},15,[603,1455,1456],{"class":608},"\u003C\u002F",[603,1458,1243],{"class":612},[603,1460,635],{"class":608},[594,1462,1464],{"className":650,"code":1463,"language":652,"meta":599,"style":599},".sheet {\n  position: fixed;\n  inset: auto 0 0 0;\n  \u002F* Up to 85% of whatever is visible now; with resizes-content the\n     keyboard shrinks the layout viewport, so dvh shrinks too. *\u002F\n  max-height: 85vh;\n  max-height: 85dvh;\n  display: grid;\n  grid-template-rows: auto minmax(0, 1fr) auto;\n  border-radius: 16px 16px 0 0;\n  background: #ffffff;\n  box-shadow: 0 -8px 24px rgb(15 23 42 \u002F 0.15);\n}\n\n.sheet__header {\n  padding: 1rem max(1rem, env(safe-area-inset-right)) 0.5rem max(1rem, env(safe-area-inset-left));\n}\n\n.sheet__body {\n  overflow: auto;\n  overscroll-behavior: contain;   \u002F* scrolling the sheet never scrolls the page *\u002F\n  padding-inline: max(1rem, env(safe-area-inset-left)) max(1rem, env(safe-area-inset-right));\n}\n\n.sheet__body:focus-visible { outline: 2px solid #2563eb; outline-offset: -2px; }\n\n.sheet__composer {\n  display: flex;\n  gap: 0.5rem;\n  padding: 0.75rem max(1rem, env(safe-area-inset-right)) max(0.75rem, env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));\n  border-top: 1px solid #e2e8f0;\n}\n\n.sheet__composer input { flex: 1; min-width: 0; font-size: 1rem; }\n.sheet__composer button { min-height: 44px; min-width: 44px; }\n\n@media (prefers-reduced-motion: no-preference) {\n  .sheet { animation: sheet-in 0.25s ease-out; }\n}\n@keyframes sheet-in { from { translate: 0 100%; } }\n",[42,1465,1466,1472,1482,1498,1503,1508,1522,1534,1544,1573,1596,1608,1650,1654,1658,1665,1713,1718,1723,1731,1742,1757,1794,1799,1804,1843,1848,1856,1868,1883,1942,1961,1966,1971,2009,2041,2046,2055,2080,2085],{"__ignoreMap":599},[603,1467,1468,1470],{"class":274,"line":605},[603,1469,1102],{"class":616},[603,1471,662],{"class":608},[603,1473,1474,1476,1478,1480],{"class":274,"line":665},[603,1475,1036],{"class":616},[603,1477,671],{"class":608},[603,1479,1041],{"class":616},[603,1481,715],{"class":608},[603,1483,1484,1486,1488,1490,1492,1494,1496],{"class":274,"line":687},[603,1485,1048],{"class":616},[603,1487,671],{"class":608},[603,1489,534],{"class":616},[603,1491,1055],{"class":616},[603,1493,1055],{"class":616},[603,1495,1055],{"class":616},[603,1497,715],{"class":608},[603,1499,1500],{"class":274,"line":704},[603,1501,1502],{"class":683},"  \u002F* Up to 85% of whatever is visible now; with resizes-content the\n",[603,1504,1505],{"class":274,"line":718},[603,1506,1507],{"class":683},"     keyboard shrinks the layout viewport, so dvh shrinks too. *\u002F\n",[603,1509,1510,1513,1515,1518,1520],{"class":274,"line":730},[603,1511,1512],{"class":616},"  max-height",[603,1514,671],{"class":608},[603,1516,1517],{"class":616},"85",[603,1519,100],{"class":677},[603,1521,715],{"class":608},[603,1523,1524,1526,1528,1530,1532],{"class":274,"line":745},[603,1525,1512],{"class":616},[603,1527,671],{"class":608},[603,1529,1517],{"class":616},[603,1531,326],{"class":677},[603,1533,715],{"class":608},[603,1535,1536,1538,1540,1542],{"class":274,"line":876},[603,1537,707],{"class":616},[603,1539,671],{"class":608},[603,1541,712],{"class":616},[603,1543,715],{"class":608},[603,1545,1546,1549,1551,1553,1556,1558,1560,1562,1564,1566,1569,1571],{"class":274,"line":881},[603,1547,1548],{"class":616},"  grid-template-rows",[603,1550,671],{"class":608},[603,1552,534],{"class":616},[603,1554,1555],{"class":616}," minmax",[603,1557,798],{"class":608},[603,1559,960],{"class":616},[603,1561,52],{"class":608},[603,1563,801],{"class":616},[603,1565,810],{"class":677},[603,1567,1568],{"class":608},") ",[603,1570,534],{"class":616},[603,1572,715],{"class":608},[603,1574,1575,1578,1580,1583,1585,1588,1590,1592,1594],{"class":274,"line":906},[603,1576,1577],{"class":616},"  border-radius",[603,1579,671],{"class":608},[603,1581,1582],{"class":616},"16",[603,1584,963],{"class":677},[603,1586,1587],{"class":616}," 16",[603,1589,963],{"class":677},[603,1591,1055],{"class":616},[603,1593,1055],{"class":616},[603,1595,715],{"class":608},[603,1597,1598,1601,1603,1606],{"class":274,"line":1359},[603,1599,1600],{"class":616},"  background",[603,1602,671],{"class":608},[603,1604,1605],{"class":616},"#ffffff",[603,1607,715],{"class":608},[603,1609,1610,1613,1615,1617,1620,1622,1625,1627,1630,1632,1635,1638,1641,1644,1647],{"class":274,"line":1389},[603,1611,1612],{"class":616},"  box-shadow",[603,1614,671],{"class":608},[603,1616,960],{"class":616},[603,1618,1619],{"class":616}," -8",[603,1621,963],{"class":677},[603,1623,1624],{"class":616}," 24",[603,1626,963],{"class":677},[603,1628,1629],{"class":616}," rgb",[603,1631,798],{"class":608},[603,1633,1634],{"class":616},"15",[603,1636,1637],{"class":616}," 23",[603,1639,1640],{"class":616}," 42",[603,1642,1643],{"class":608}," \u002F ",[603,1645,1646],{"class":616},"0.15",[603,1648,1649],{"class":608},");\n",[603,1651,1652],{"class":274,"line":1421},[603,1653,748],{"class":608},[603,1655,1656],{"class":274,"line":1444},[603,1657,1024],{"emptyLinePlaceholder":1023},[603,1659,1660,1663],{"class":274,"line":1453},[603,1661,1662],{"class":616},".sheet__header",[603,1664,662],{"class":608},[603,1666,1668,1670,1672,1674,1676,1679,1681,1683,1685,1687,1690,1693,1695,1697,1700,1702,1704,1706,1708,1711],{"class":274,"line":1667},16,[603,1669,733],{"class":616},[603,1671,671],{"class":608},[603,1673,801],{"class":616},[603,1675,740],{"class":677},[603,1677,1678],{"class":616}," max",[603,1680,798],{"class":608},[603,1682,801],{"class":616},[603,1684,740],{"class":677},[603,1686,52],{"class":608},[603,1688,1689],{"class":839},"env(safe-area-inset-right",[603,1691,1692],{"class":608},")) 0.5",[603,1694,740],{"class":616},[603,1696,1678],{"class":616},[603,1698,1699],{"class":608},"(1",[603,1701,740],{"class":616},[603,1703,52],{"class":608},[603,1705,983],{"class":616},[603,1707,798],{"class":608},[603,1709,1710],{"class":616},"safe-area-inset-left",[603,1712,991],{"class":608},[603,1714,1716],{"class":274,"line":1715},17,[603,1717,748],{"class":608},[603,1719,1721],{"class":274,"line":1720},18,[603,1722,1024],{"emptyLinePlaceholder":1023},[603,1724,1726,1729],{"class":274,"line":1725},19,[603,1727,1728],{"class":616},".sheet__body",[603,1730,662],{"class":608},[603,1732,1734,1736,1738,1740],{"class":274,"line":1733},20,[603,1735,1158],{"class":616},[603,1737,671],{"class":608},[603,1739,534],{"class":616},[603,1741,715],{"class":608},[603,1743,1745,1747,1749,1751,1754],{"class":274,"line":1744},21,[603,1746,1169],{"class":616},[603,1748,671],{"class":608},[603,1750,537],{"class":616},[603,1752,1753],{"class":608},";   ",[603,1755,1756],{"class":683},"\u002F* scrolling the sheet never scrolls the page *\u002F\n",[603,1758,1760,1762,1764,1766,1768,1770,1772,1774,1776,1778,1780,1782,1784,1786,1788,1790,1792],{"class":274,"line":1759},22,[603,1761,950],{"class":616},[603,1763,671],{"class":608},[603,1765,955],{"class":616},[603,1767,798],{"class":608},[603,1769,801],{"class":616},[603,1771,740],{"class":677},[603,1773,52],{"class":608},[603,1775,968],{"class":839},[603,1777,971],{"class":608},[603,1779,955],{"class":616},[603,1781,1699],{"class":608},[603,1783,740],{"class":616},[603,1785,52],{"class":608},[603,1787,983],{"class":616},[603,1789,798],{"class":608},[603,1791,988],{"class":616},[603,1793,991],{"class":608},[603,1795,1797],{"class":274,"line":1796},23,[603,1798,748],{"class":608},[603,1800,1802],{"class":274,"line":1801},24,[603,1803,1024],{"emptyLinePlaceholder":1023},[603,1805,1807,1810,1812,1815,1817,1820,1822,1825,1828,1831,1834,1836,1839,1841],{"class":274,"line":1806},25,[603,1808,1809],{"class":616},".sheet__body:focus-visible",[603,1811,892],{"class":608},[603,1813,1814],{"class":616},"outline",[603,1816,671],{"class":608},[603,1818,1819],{"class":616},"2",[603,1821,963],{"class":677},[603,1823,1824],{"class":616}," solid",[603,1826,1827],{"class":616}," #2563eb",[603,1829,1830],{"class":608},"; ",[603,1832,1833],{"class":616},"outline-offset",[603,1835,671],{"class":608},[603,1837,1838],{"class":616},"-2",[603,1840,963],{"class":677},[603,1842,903],{"class":608},[603,1844,1846],{"class":274,"line":1845},26,[603,1847,1024],{"emptyLinePlaceholder":1023},[603,1849,1851,1854],{"class":274,"line":1850},27,[603,1852,1853],{"class":616},".sheet__composer",[603,1855,662],{"class":608},[603,1857,1859,1861,1863,1866],{"class":274,"line":1858},28,[603,1860,707],{"class":616},[603,1862,671],{"class":608},[603,1864,1865],{"class":616},"flex",[603,1867,715],{"class":608},[603,1869,1871,1874,1876,1879,1881],{"class":274,"line":1870},29,[603,1872,1873],{"class":616},"  gap",[603,1875,671],{"class":608},[603,1877,1878],{"class":616},"0.5",[603,1880,740],{"class":677},[603,1882,715],{"class":608},[603,1884,1886,1888,1890,1892,1894,1896,1898,1900,1902,1904,1906,1908,1910,1913,1915,1917,1919,1921,1924,1926,1928,1930,1932,1934,1936,1938,1940],{"class":274,"line":1885},30,[603,1887,733],{"class":616},[603,1889,671],{"class":608},[603,1891,1075],{"class":616},[603,1893,740],{"class":677},[603,1895,1678],{"class":616},[603,1897,798],{"class":608},[603,1899,801],{"class":616},[603,1901,740],{"class":677},[603,1903,52],{"class":608},[603,1905,1689],{"class":839},[603,1907,971],{"class":608},[603,1909,955],{"class":616},[603,1911,1912],{"class":608},"(0.75",[603,1914,740],{"class":616},[603,1916,52],{"class":608},[603,1918,983],{"class":616},[603,1920,798],{"class":608},[603,1922,1923],{"class":616},"safe-area-inset-bottom",[603,1925,971],{"class":608},[603,1927,955],{"class":616},[603,1929,1699],{"class":608},[603,1931,740],{"class":616},[603,1933,52],{"class":608},[603,1935,983],{"class":616},[603,1937,798],{"class":608},[603,1939,1710],{"class":616},[603,1941,991],{"class":608},[603,1943,1945,1948,1950,1952,1954,1956,1959],{"class":274,"line":1944},31,[603,1946,1947],{"class":616},"  border-top",[603,1949,671],{"class":608},[603,1951,801],{"class":616},[603,1953,963],{"class":677},[603,1955,1824],{"class":616},[603,1957,1958],{"class":616}," #e2e8f0",[603,1960,715],{"class":608},[603,1962,1964],{"class":274,"line":1963},32,[603,1965,748],{"class":608},[603,1967,1969],{"class":274,"line":1968},33,[603,1970,1024],{"emptyLinePlaceholder":1023},[603,1972,1974,1976,1979,1981,1983,1985,1987,1989,1992,1994,1996,1998,2001,2003,2005,2007],{"class":274,"line":1973},34,[603,1975,1853],{"class":616},[603,1977,1978],{"class":612}," input",[603,1980,892],{"class":608},[603,1982,1865],{"class":616},[603,1984,671],{"class":608},[603,1986,801],{"class":616},[603,1988,1830],{"class":608},[603,1990,1991],{"class":616},"min-width",[603,1993,671],{"class":608},[603,1995,960],{"class":616},[603,1997,1830],{"class":608},[603,1999,2000],{"class":616},"font-size",[603,2002,671],{"class":608},[603,2004,801],{"class":616},[603,2006,740],{"class":677},[603,2008,903],{"class":608},[603,2010,2012,2014,2017,2019,2022,2024,2027,2029,2031,2033,2035,2037,2039],{"class":274,"line":2011},35,[603,2013,1853],{"class":616},[603,2015,2016],{"class":612}," button",[603,2018,892],{"class":608},[603,2020,2021],{"class":616},"min-height",[603,2023,671],{"class":608},[603,2025,2026],{"class":616},"44",[603,2028,963],{"class":677},[603,2030,1830],{"class":608},[603,2032,1991],{"class":616},[603,2034,671],{"class":608},[603,2036,2026],{"class":616},[603,2038,963],{"class":677},[603,2040,903],{"class":608},[603,2042,2044],{"class":274,"line":2043},36,[603,2045,1024],{"emptyLinePlaceholder":1023},[603,2047,2049,2052],{"class":274,"line":2048},37,[603,2050,2051],{"class":677},"@media",[603,2053,2054],{"class":608}," (prefers-reduced-motion: no-preference) {\n",[603,2056,2058,2061,2063,2066,2069,2072,2075,2078],{"class":274,"line":2057},38,[603,2059,2060],{"class":616},"  .sheet",[603,2062,892],{"class":608},[603,2064,2065],{"class":616},"animation",[603,2067,2068],{"class":608},": sheet-in ",[603,2070,2071],{"class":616},"0.25",[603,2073,2074],{"class":677},"s",[603,2076,2077],{"class":616}," ease-out",[603,2079,903],{"class":608},[603,2081,2083],{"class":274,"line":2082},39,[603,2084,748],{"class":608},[603,2086,2088,2091,2094,2096,2099,2101,2104,2106,2108,2111,2113],{"class":274,"line":2087},40,[603,2089,2090],{"class":677},"@keyframes",[603,2092,2093],{"class":839}," sheet-in",[603,2095,892],{"class":608},[603,2097,2098],{"class":616},"from",[603,2100,892],{"class":608},[603,2102,2103],{"class":616},"translate",[603,2105,671],{"class":608},[603,2107,960],{"class":616},[603,2109,2110],{"class":616}," 100",[603,2112,836],{"class":677},[603,2114,2115],{"class":608},"; } }\n",[14,2117,2118,2119,2122,2123,2125,2126,2129,2130,2133,2134,67],{},"Four decisions carry the component. ",[42,2120,2121],{},"minmax(0, 1fr)"," on the middle row lets the body shrink and scroll instead of pushing the composer off screen. The composer's bottom padding uses ",[42,2124,59],{}," with the inset so its button clears the home indicator. The input's ",[42,2127,2128],{},"font-size: 1rem"," avoids an automatic zoom that some mobile browsers apply to inputs with text smaller than 16 pixels. And the entrance animation is gated on ",[42,2131,2132],{},"prefers-reduced-motion",", following the approach in ",[18,2135,2137],{"href":2136},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Freducing-motion-preferences-in-css\u002F","Reducing Motion Preferences in CSS",[77,2139],{},[80,2141,2143],{"id":2142},"integration-with-adjacent-css-features","Integration With Adjacent CSS Features",[14,2145,2146,2149,2150,2153,2154,2157,2158,2161],{},[31,2147,2148],{},"Media queries."," Viewport units and viewport media queries measure the same box, so a ",[42,2151,2152],{},"@media (height \u003C 30rem)"," query is the natural companion for short landscape phones where even ",[42,2155,2156],{},"100svh"," heroes are too tall to hold their content. Range syntax such as ",[42,2159,2160],{},"(width >= 40rem)"," keeps these conditions readable.",[14,2163,2164,2167,2168,2170,2171,2174,2175,2177,2178,67],{},[31,2165,2166],{},"Scroll snapping."," Full-screen snap sections — story-style pages where each panel fills the screen — should use ",[42,2169,2156],{}," panels with ",[42,2172,2173],{},"scroll-snap-align: start",". Using ",[42,2176,326],{}," makes the snap points move as the toolbar retracts, which feels like the page fighting the user's thumb. The overflow and snapping patterns are covered in ",[18,2179,2181],{"href":2180},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002F","Scroll Snap & Overflow Layouts",[14,2183,2184,2187,2188,2191],{},[31,2185,2186],{},"Sticky positioning."," A ",[42,2189,2190],{},"position: sticky"," header sticks to the top of the layout viewport. Safe-area padding belongs on the sticky element itself, so its background extends under the status bar while its content clears it.",[14,2193,2194,2187,2197,2200],{},[31,2195,2196],{},"Scroll-driven animations.",[42,2198,2199],{},"scroll()"," timeline on the root scroller measures the document's scroll range, which itself depends on the viewport height. Progress indicators therefore stay correct as the toolbar moves, but a timeline range written in viewport units inherits the same trade-offs as any other length — prefer percentages of the timeline.",[14,2202,2203,2206,2207,2209,2210,2213,2214,2216],{},[31,2204,2205],{},"Cascade layers and tokens."," Put viewport-dependent tokens — hero height, sheet maximum height — in a tokens layer as custom properties, with the ",[42,2208,100],{}," fallback and the modern unit declared together. Components then reference ",[42,2211,2212],{},"var(--hero-min)"," and never repeat the fallback pair. When a later redesign changes the hero from ",[42,2215,304],{}," to a clamped value, the change happens in one place and every page that uses the token follows.",[77,2218],{},[80,2220,2222],{"id":2221},"performance-and-accessibility-notes","Performance and Accessibility Notes",[14,2224,2225,2228,2229,2231,2232,2234,2235,2237],{},[31,2226,2227],{},"Dynamic units cost layout."," Anything sized with ",[42,2230,326],{}," is re-laid out as the toolbars move. Browsers throttle these updates, but in-flow content sized with ",[42,2233,326],{}," still shifts the content below it mid-scroll and can register as layout shift. Reserve ",[42,2236,326],{}," for out-of-flow elements.",[14,2239,2240,2243,2244,2246,2247,67],{},[31,2241,2242],{},"Zoom and text."," Pure viewport-unit font sizes barely respond to browser zoom, which fails WCAG 1.4.4 Resize Text. Always combine them with ",[42,2245,740],{}," in ",[42,2248,51],{},[14,2250,2251,2254,2255,2257,2258,2260,2261,2263],{},[31,2252,2253],{},"Reflow at 320 pixels."," WCAG 1.4.10 asks that content reflow without horizontal scrolling at 320 CSS pixels wide. Minimum widths in ",[42,2256,97],{}," are harmless, but fixed minimum widths in pixels or ",[42,2259,740],{}," on full-width elements, and ",[42,2262,245],{}," elements on desktop platforms, commonly break it.",[14,2265,2266,2269,2270,67],{},[31,2267,2268],{},"Operable targets near edges."," Controls under the home indicator or in a notch's shadow are hard to activate. Safe-area padding and 44-pixel targets together keep bottom bars usable, as covered in ",[18,2271,2273],{"href":2272},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Ftarget-size-and-pointer-accessibility\u002F","Target Size and Pointer Accessibility",[14,2275,2276,2279,2280,2283],{},[31,2277,2278],{},"Scrollable regions need focus."," A sheet body that scrolls must be keyboard reachable, which is why the example gives it ",[42,2281,2282],{},"tabindex=\"0\""," and a visible focus style.",[122,2285,129,2288,129,2291,129,2294,129,2297,129,2303,129,2309,129,2314,129,2318,129,2321,129,2325,129,2327,129,2330,129,2332,129,2336,129,2338,129,2341,129,2344,129,2348,129,2350,129,2353,129,2356,129,2360,129,2362],{"viewBox":2286,"role":125,"ariaLabel":2287,"xmlns":127,"style":128},"0 0 720 260","Summary grid of which unit or feature prevents which mobile failure",[131,2289,2290],{},"Mobile failures and their fixes",[135,2292,2293],{},"Content under the toolbar is fixed with svh. Gaps when the toolbar hides are fixed with lvh. Overlays not fitting are fixed with dvh. Controls under the notch or indicator are fixed with safe-area insets. Horizontal scrollbars from full-width bands are fixed with the named-line grid.",[139,2295,2296],{"textAnchor":141,"x":142,"y":143,"style":144},"Five mobile failures, five fixes",[164,2298],{"x":2299,"y":2300,"width":2301,"height":2302,"rx":154,"fill":150,"stroke":151,"strokeWidth":152,"opacity":1878},"30","46","420","36",[139,2304,2308],{"textAnchor":2305,"x":2300,"y":2306,"style":2307},"start","69","text-anchor:start;fill:currentColor;font:13px sans-serif","Call to action hidden under the toolbar on load",[164,2310],{"x":2311,"y":2300,"width":2312,"height":2302,"rx":154,"fill":170,"opacity":2313},"470","220","0.3",[139,2315,2156],{"textAnchor":141,"x":2316,"y":2306,"style":2317},"580","text-anchor:middle;fill:currentColor;font:13px ui-monospace,monospace",[164,2319],{"x":2299,"y":2320,"width":2301,"height":2302,"rx":154,"fill":150,"stroke":151,"strokeWidth":152,"opacity":1878},"88",[139,2322,2324],{"textAnchor":2305,"x":2300,"y":2323,"style":2307},"111","Bare strip when the toolbar retracts",[164,2326],{"x":2311,"y":2320,"width":2312,"height":2302,"rx":154,"fill":170,"opacity":2313},[139,2328,2329],{"textAnchor":141,"x":2316,"y":2323,"style":2317},"100lvh",[164,2331],{"x":2299,"y":199,"width":2301,"height":2302,"rx":154,"fill":150,"stroke":151,"strokeWidth":152,"opacity":1878},[139,2333,2335],{"textAnchor":2305,"x":2300,"y":2334,"style":2307},"153","Overlay taller or shorter than the screen",[164,2337],{"x":2311,"y":199,"width":2312,"height":2302,"rx":154,"fill":170,"opacity":2313},[139,2339,2340],{"textAnchor":141,"x":2316,"y":2334,"style":2317},"100dvh",[164,2342],{"x":2299,"y":2343,"width":2301,"height":2302,"rx":154,"fill":150,"stroke":151,"strokeWidth":152,"opacity":1878},"172",[139,2345,2347],{"textAnchor":2305,"x":2300,"y":2346,"style":2307},"195","Buttons under the notch or home indicator",[164,2349],{"x":2311,"y":2343,"width":2312,"height":2302,"rx":154,"fill":170,"opacity":2313},[139,2351,2352],{"textAnchor":141,"x":2316,"y":2346,"style":178},"max(pad, env(…))",[164,2354],{"x":2299,"y":2355,"width":2301,"height":2302,"rx":154,"fill":150,"stroke":151,"strokeWidth":152,"opacity":1878},"214",[139,2357,2359],{"textAnchor":2305,"x":2300,"y":2358,"style":2307},"237","Horizontal scrollbar from a 100vw band",[164,2361],{"x":2311,"y":2355,"width":2312,"height":2302,"rx":154,"fill":170,"opacity":2313},[139,2363,2364],{"textAnchor":141,"x":2316,"y":2358,"style":2317},"named-line grid",[77,2366],{},[80,2368,2370],{"id":2369},"devtools-debugging-workflow","DevTools Debugging Workflow",[2372,2373,2374,2387,2404,2419,2436],"ol",{},[38,2375,2376,2379,2380,52,2382,56,2384,2386],{},[31,2377,2378],{},"Device emulation is not enough for toolbars."," Chrome's and Firefox's responsive modes emulate width and device pixel ratio but not retracting toolbars, so ",[42,2381,304],{},[42,2383,296],{},[42,2385,326],{}," all report the same value there. Test viewport-height behaviour on a real device or a platform simulator.",[38,2388,2389,2392,2393,2396,2397,56,2400,2403],{},[31,2390,2391],{},"Remote debugging."," Connect an Android device to Chrome via ",[42,2394,2395],{},"chrome:\u002F\u002Finspect",", or an iPhone to Safari's Develop menu, and inspect the live page. Evaluate ",[42,2398,2399],{},"innerHeight",[42,2401,2402],{},"visualViewport.height"," in the console while scrolling to watch the two viewports diverge.",[38,2405,2406,2409,2410,2412,2413,2415,2416,2418],{},[31,2407,2408],{},"Safe areas."," The iOS Simulator and Android emulators with display cut-outs report real ",[42,2411,497],{}," values. In the Computed pane, padding that uses ",[42,2414,59],{}," shows its resolved pixel value, which confirms which side of the ",[42,2417,59],{}," won.",[38,2420,2421,2424,2425,2428,2429,2432,2433,2435],{},[31,2422,2423],{},"Scrollbar overhang."," On Windows or Linux, or with macOS set to always show scrollbars, compare ",[42,2426,2427],{},"document.documentElement.clientWidth"," with ",[42,2430,2431],{},"innerWidth","; the difference is the scrollbar width that ",[42,2434,245],{}," includes.",[38,2437,2438,2441,2442,2445],{},[31,2439,2440],{},"Keyboard behaviour."," Focus an input near the bottom of the page on a device and watch whether fixed elements move. If they stay put and are covered, the browser is overlaying the keyboard; ",[42,2443,2444],{},"interactive-widget=resizes-content"," changes that where supported.",[77,2447],{},[80,2449,2451],{"id":2450},"browser-compatibility","Browser Compatibility",[360,2453,2454,2470],{},[363,2455,2456],{},[366,2457,2458,2461,2464,2467],{},[369,2459,2460],{},"Feature",[369,2462,2463],{},"Chrome \u002F Edge",[369,2465,2466],{},"Firefox",[369,2468,2469],{},"Safari",[379,2471,2472,2492,2512,2531,2547,2561],{},[366,2473,2474,2483,2486,2489],{},[384,2475,2476,1643,2478,1643,2480,2482],{},[42,2477,304],{},[42,2479,296],{},[42,2481,326],{}," and variants",[384,2484,2485],{},"108+",[384,2487,2488],{},"101+",[384,2490,2491],{},"15.4+",[366,2493,2494,2503,2506,2509],{},[384,2495,2496,2497,52,2499,2502],{},"Container query units (",[42,2498,351],{},[42,2500,2501],{},"cqb",")",[384,2504,2505],{},"105+",[384,2507,2508],{},"110+",[384,2510,2511],{},"16+",[366,2513,2514,2522,2525,2528],{},[384,2515,2516,1643,2518,1643,2520],{},[42,2517,55],{},[42,2519,59],{},[42,2521,51],{},[384,2523,2524],{},"79+",[384,2526,2527],{},"75+",[384,2529,2530],{},"13.1+",[366,2532,2533,2539,2542,2545],{},[384,2534,2535,2538],{},[42,2536,2537],{},"subgrid"," (nested full-bleed)",[384,2540,2541],{},"117+",[384,2543,2544],{},"71+",[384,2546,2511],{},[366,2548,2549,2552,2555,2558],{},[384,2550,2551],{},"CSS Grid named lines",[384,2553,2554],{},"57+ \u002F 16+",[384,2556,2557],{},"52+",[384,2559,2560],{},"10.1+",[366,2562,2563,2567,2570,2572],{},[384,2564,2565],{},[42,2566,497],{},[384,2568,2569],{},"Supported on current mobile versions",[384,2571,2569],{},[384,2573,2574],{},"Supported on current versions",[14,2576,2577,2579],{},[42,2578,552],{}," in the viewport meta tag is honoured by Chromium-based mobile browsers and ignored elsewhere, so treat it as an enhancement.",[77,2581],{},[80,2583,2585],{"id":2584},"common-pitfalls","Common Pitfalls",[360,2587,2588,2601],{},[363,2589,2590],{},[366,2591,2592,2595,2598],{},[369,2593,2594],{},"Pitfall",[369,2596,2597],{},"Cause",[369,2599,2600],{},"Resolution",[379,2602,2603,2623,2641,2657,2670],{},[366,2604,2605,2608,2614],{},[384,2606,2607],{},"Hero's bottom cut off on load",[384,2609,2610,2613],{},[42,2611,2612],{},"100vh"," is the large viewport on mobile",[384,2615,2616,2619,2620,2622],{},[42,2617,2618],{},"min-height: 100svh"," with a ",[42,2621,100],{}," fallback",[366,2624,2625,2628,2633],{},[384,2626,2627],{},"Content jumps while scrolling",[384,2629,2630,2631],{},"In-flow element sized with ",[42,2632,326],{},[384,2634,48,2635,2637,2638,2640],{},[42,2636,304],{}," for in-flow, ",[42,2639,326],{}," only for overlays",[366,2642,2643,2646,2651],{},[384,2644,2645],{},"Horizontal scrollbar on Windows",[384,2647,2648,2650],{},[42,2649,245],{}," includes the scrollbar",[384,2652,2653,2654,2656],{},"Named-line grid, or ",[42,2655,351],{}," on a container",[366,2658,2659,2662,2667],{},[384,2660,2661],{},"Insets always zero",[384,2663,2664,2665],{},"Missing ",[42,2666,521],{},[384,2668,2669],{},"Add it to the viewport meta tag",[366,2671,2672,2675,2680],{},[384,2673,2674],{},"Doubled bottom padding on iPhone",[384,2676,2677],{},[42,2678,2679],{},"calc(pad + inset)",[384,2681,2682],{},[42,2683,2684],{},"max(pad, inset)",[77,2686],{},[80,2688,2690],{"id":2689},"faq","FAQ",[14,2692,2693,2696],{},[31,2694,2695],{},"What is the difference between the layout viewport and the visual viewport?","\nThe layout viewport is the box that CSS layout, fixed positioning and viewport units are measured against. The visual viewport is the part of the page currently visible on screen, which shrinks when the user pinch-zooms or the on-screen keyboard opens. Most layout rules only ever see the layout viewport.",[14,2698,2699,2702,2703,2705,2706,2708],{},[31,2700,2701],{},"Why does my full-height section overflow on mobile but not on desktop?","\nBecause ",[42,2704,2612],{}," on mobile browsers means the height with the retractable toolbars hidden. When the page loads, the toolbars are showing and the visible area is shorter, so the section extends below the fold. Use ",[42,2707,2156],{}," for sections that must fit on load.",[14,2710,2711,2714,2715,2717,2718,2720],{},[31,2712,2713],{},"Do I still need the viewport meta tag?","\nYes. Without ",[42,2716,44],{},", mobile browsers lay pages out at a desktop-like width and scale them down, so every viewport unit and media query sees the wrong width. Add ",[42,2719,521],{}," only if you also handle safe-area insets.",[14,2722,2723,2726,2727,2729,2730,2732,2733,2735,2736,2738,2739,2741],{},[31,2724,2725],{},"Are viewport units bad for accessibility?","\nNot in themselves, but font sizes in pure ",[42,2728,97],{}," fail WCAG 1.4.4 because browser zoom barely changes them. Combine viewport units with ",[42,2731,740],{}," inside ",[42,2734,51],{}," for text, and prefer ",[42,2737,304],{}," over ",[42,2740,100],{}," for heights so content is not hidden under browser UI.",[14,2743,2744,2747,2748,2750],{},[31,2745,2746],{},"When should I use container units instead of viewport units?","\nWhenever the dimension belongs to a component rather than to the screen. Padding, gaps and heading sizes of a card should follow the card's width via ",[42,2749,351],{},"; the maximum height of an overlay or the height of a page hero should follow the screen.",[80,2752,2754],{"id":2753},"related","Related",[35,2756,2757,2762,2767,2772,2777,2784],{},[38,2758,2759,2761],{},[18,2760,231],{"href":230}," — the three viewport heights and when to use each.",[38,2763,2764,2766],{},[18,2765,236],{"href":235}," — edge-to-edge drawing done safely.",[38,2768,2769,2771],{},[18,2770,241],{"href":240}," — breaking out of a reading column.",[38,2773,2774,2776],{},[18,2775,250],{"href":249}," — choosing the right reference box.",[38,2778,2779,2783],{},[18,2780,2782],{"href":2781},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002F","Fluid Typography With clamp()"," — type scales built on these units.",[38,2785,2786,2790],{},[18,2787,2789],{"href":2788},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002F","Scroll-Driven Animations"," — motion tied to the same scrolling viewport.",[2792,2793,2794],"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 .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}",{"title":599,"searchDepth":665,"depth":665,"links":2796},[2797,2801,2802,2809,2810,2811,2812,2813,2814,2815,2816],{"id":82,"depth":665,"text":83,"children":2798},[2799,2800],{"id":255,"depth":687,"text":256},{"id":338,"depth":687,"text":339},{"id":357,"depth":665,"text":358},{"id":587,"depth":665,"text":588,"children":2803},[2804,2805,2806,2807,2808],{"id":591,"depth":687,"text":592},{"id":646,"depth":687,"text":647},{"id":756,"depth":687,"text":757},{"id":929,"depth":687,"text":930},{"id":1091,"depth":687,"text":1092},{"id":1193,"depth":665,"text":1194},{"id":2142,"depth":665,"text":2143},{"id":2221,"depth":665,"text":2222},{"id":2369,"depth":665,"text":2370},{"id":2450,"depth":665,"text":2451},{"id":2584,"depth":665,"text":2585},{"id":2689,"depth":665,"text":2690},{"id":2753,"depth":665,"text":2754},"The mobile viewport explained for layout: layout and visual viewports, dvh, svh and lvh, safe-area insets, full-bleed sections and when to use container units.","md",{"pageTitle":2820,"datePublished":2821,"dateModified":2821,"faq":2822},"Viewport Units and Mobile Layout in CSS","2026-09-18",[2823,2825,2827,2829,2831],{"q":2695,"a":2824},"The layout viewport is the box that CSS layout, fixed positioning and viewport units are measured against. The visual viewport is the part of the page currently visible on screen, which shrinks when the user pinch-zooms or the on-screen keyboard opens. Most layout rules only ever see the layout viewport.",{"q":2701,"a":2826},"Because 100vh on mobile browsers means the height with the retractable toolbars hidden. When the page loads, the toolbars are showing and the visible area is shorter, so the section extends below the fold. Use 100svh for sections that must fit on load.",{"q":2713,"a":2828},"Yes. Without width=device-width, mobile browsers lay pages out at a desktop-like width and scale them down, so every viewport unit and media query sees the wrong width. Add viewport-fit=cover only if you also handle safe-area insets.",{"q":2725,"a":2830},"Not in themselves, but font sizes in pure vw fail WCAG 1.4.4 because browser zoom barely changes them. Combine viewport units with rem inside clamp() for text, and prefer svh over vh for heights so content is not hidden under browser UI.",{"q":2746,"a":2832},"Whenever the dimension belongs to a component rather than to the screen. Padding, gaps and heading sizes of a card should follow the card's width via cqi; the maximum height of an overlay or the height of a page hero should follow the screen.","\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout",{"title":5,"description":2817},"mastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Findex","q28pgN3sUsz7Bx2CNv9xMp9SWoc--TSr-6XIBrxeMTg",[2838,2841,2844,2847,2850,2853,2856,2859,2862,2865,2868,2871,2874,2877,2880,2883,2886,2889,2892,2895,2898,2901,2904,2907,2910,2913,2916,2919,2922,2925,2928,2931,2934,2937,2940,2943,2946,2949,2952,2955,2958,2961,2964,2967,2970,2973,2976,2979,2982,2985,2988,2991,2994,2997,3000,3003,3006,3009,3012,3015,3018,3021,3024,3027,3030,3033,3036,3039,3042,3045,3048,3051,3054,3057,3060,3063,3066,3069,3072,3075,3078,3081,3084,3087,3090,3093,3096,3099,3102,3105,3108,3111,3114,3117,3120,3123,3126,3129,3132,3135,3138,3141,3144,3147,3150,3153,3156,3159,3162,3165,3168,3171,3174,3177,3180,3183,3186,3189,3192,3195,3198,3201,3204,3207,3210,3213,3216,3219,3222,3225,3228,3231,3234,3237,3240,3243,3246,3249,3252,3255,3258,3260,3263,3266,3269,3272,3275,3278,3281,3284,3287,3290,3293,3296,3299,3302,3305,3308,3311,3314,3317,3320,3323,3326,3329,3332,3335,3338,3341,3344,3347,3350,3353,3356,3359,3362,3365,3368,3371,3374,3377,3380,3383,3386,3387,3390,3393],{"path":2839,"title":2840},"\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":2842,"title":2843},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds","Flashing Content and Seizure Thresholds",{"path":2845,"title":2846},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fforced-colors-mode-and-animations","Forced Colors Mode and Animations",{"path":2848,"title":2849},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":2851,"title":2852},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fpause-controls-for-looping-animations","Pause Controls for Looping CSS Animations: Meeting WCAG 2.2.2",{"path":2854,"title":2855},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":2857,"title":2858},"\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":2860,"title":2861},"\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":2863,"title":2864},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":2866,"title":2867},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":2869,"title":2870},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fanimated-gradient-borders-with-property","Animated Gradient Borders With @property: A Spinning Highlight Without Extra Elements",{"path":2872,"title":2873},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fclip-path-reveal-animations","Clip-Path Reveal Animations: Wipes, Irises and Corners Without Extra Markup",{"path":2875,"title":2876},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations","Clip-Path & Mask Animations: Animating Visibility Instead of Position",{"path":2878,"title":2879},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fmask-image-fade-edges","Fading Edges With mask-image: Soft Boundaries That Work on Any Background",{"path":2881,"title":2882},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fmorphing-shapes-with-clip-path-polygon","Morphing Shapes With clip-path: polygon(): Point-Matched Transitions",{"path":2884,"title":2885},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fanimating-gradients","Animating CSS Gradients: Smooth Colour Motion Without Jumps",{"path":2887,"title":2888},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fcolor-mix-hover-states","Hover and Active States With color-mix(): One Token, Every Shade",{"path":2890,"title":2891},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions","Color & Theme Transitions: Colour as Part of the Motion System",{"path":2893,"title":2894},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Flight-dark-function-for-themes","Light and Dark Themes With light-dark(): One Declaration per Colour",{"path":2896,"title":2897},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fsmooth-theme-switching-transitions","Smooth Theme Switching: Crossfades, Circular Reveals and No Flash",{"path":2899,"title":2900},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":2902,"title":2903},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":2905,"title":2906},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Flayout-change-animations-at-container-breakpoints","Animating Changes at Container Breakpoints",{"path":2908,"title":2909},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries","Motion Driven by Container Style Queries",{"path":2911,"title":2912},"\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":2914,"title":2915},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":2917,"title":2918},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript","Controlling CSS Animations From JavaScript",{"path":2920,"title":2921},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":2923,"title":2924},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui","Interruptible UI: CSS Transitions vs WAAPI",{"path":2926,"title":2927},"\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":2929,"title":2930},"\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":2932,"title":2933},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values","Custom Property Fallbacks and Invalid Values",{"path":2935,"title":2936},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":2938,"title":2939},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":2941,"title":2942},"\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":2944,"title":2945},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components","Scoping Custom Properties to Components",{"path":2947,"title":2948},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":2950,"title":2951},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":2953,"title":2954},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions","Interrupted and Reversing Transitions: What Happens Mid-Flight",{"path":2956,"title":2957},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":2959,"title":2960},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-delay-choreography","Choreographing Motion With transition-delay",{"path":2962,"title":2963},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties","The transition Shorthand and Multiple Properties",{"path":2965,"title":2966},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":2968,"title":2969},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fanimating-dialog-open-and-close","Animating \u003Cdialog> Open and Close: Both Directions, No Library",{"path":2971,"title":2972},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fbackdrop-animations","Animating ::backdrop: Fades and Blurs Behind Dialogs and Popovers",{"path":2974,"title":2975},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations","Dialog & Popover Animations: Motion for the Top Layer",{"path":2977,"title":2978},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Finterpolate-size-for-height-auto-animation","Animating to height: auto With interpolate-size and calc-size()",{"path":2980,"title":2981},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fpopover-entry-and-exit-transitions","Popover Menus That Animate From Their Anchor",{"path":2983,"title":2984},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations","Choosing Animation Durations: How Long Motion Should Last",{"path":2986,"title":2987},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fcubic-bezier-overshoot-and-anticipation","Overshoot and Anticipation With cubic-bezier(): Motion With Character",{"path":2989,"title":2990},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fentry-vs-exit-easing","Entry vs Exit Easing: Different Curves for Arriving and Leaving",{"path":2992,"title":2993},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design","Easing & Motion Design: Making CSS Motion Feel Intentional",{"path":2995,"title":2996},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Flinear-easing-function-for-springs","Spring and Bounce Easing With linear(): Physical Motion Without JavaScript",{"path":2998,"title":2999},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fsteps-easing-for-sprite-animations","steps() Easing: Sprite Sheets, Typewriters and Other Frame-by-Frame Effects",{"path":3001,"title":3002},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":3004,"title":3005},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fbutton-press-and-active-states","Button Press and  States",{"path":3007,"title":3008},"\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":3010,"title":3011},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":3013,"title":3014},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fhover-intent-delays-with-transition-delay","Hover Intent Delays With transition-delay: Menus That Don't Flicker",{"path":3016,"title":3017},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":3019,"title":3020},"\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":3022,"title":3023},"\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":3025,"title":3026},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":3028,"title":3029},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-composition-and-stacking","Stacking Animations With animation-composition",{"path":3031,"title":3032},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-fill-mode-explained","animation-fill-mode: What an Animation Applies Before and After It Runs",{"path":3034,"title":3035},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":3037,"title":3038},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":3040,"title":3041},"\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":3043,"title":3044},"\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":3046,"title":3047},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":3049,"title":3050},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fmulti-step-keyframes-and-per-keyframe-easing","Multi-Step Keyframes and Per-Keyframe Easing",{"path":3052,"title":3053},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":3055,"title":3056},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fanimating-box-shadow-and-filters-cheaply","Animating box-shadow and Filters Cheaply",{"path":3058,"title":3059},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcontain-property-for-animation-performance","The contain Property for Animation Performance",{"path":3061,"title":3062},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcss-triggers-layout-paint-composite","Layout, Paint and Composite: What Triggers What",{"path":3064,"title":3065},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":3067,"title":3068},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":3070,"title":3071},"\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":3073,"title":3074},"\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":3076,"title":3077},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":3079,"title":3080},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":3082,"title":3083},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-parallax-effects","Scroll-Driven Parallax Effects in CSS",{"path":3085,"title":3086},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":3088,"title":3089},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":3091,"title":3092},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Ftimeline-scope-for-cross-element-animations","timeline-scope for Cross-Element Animations",{"path":3094,"title":3095},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fview-timeline-and-animation-range","View Timelines and animation-range",{"path":3097,"title":3098},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fcross-document-view-transitions","Cross-Document View Transitions",{"path":3100,"title":3101},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":3103,"title":3104},"\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":3106,"title":3107},"\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":3109,"title":3110},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-types-and-classes","View Transition Types and Classes",{"path":3112,"title":3113},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-for-list-reordering","View Transitions for List Reordering",{"path":3115,"title":3116},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":3118,"title":3119},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":3121,"title":3122},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":3124,"title":3125},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":3127,"title":3128},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-size-for-matching-widths","anchor-size(): Overlays That Match Their Trigger's Size",{"path":3130,"title":3131},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":3133,"title":3134},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":3136,"title":3137},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-light-dismiss-and-stacking","Popover Light Dismiss, Nesting and Stacking",{"path":3139,"title":3140},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fposition-area-grid-explained","position-area: The Anchor Placement Grid",{"path":3142,"title":3143},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fcontainer-query-polyfill-tradeoffs","Container Query Polyfills: What They Cost and When to Skip Them",{"path":3145,"title":3146},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":3148,"title":3149},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":3151,"title":3152},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":3154,"title":3155},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fintrinsic-layout-fallbacks-without-queries","Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query",{"path":3157,"title":3158},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ftesting-fallbacks-without-old-browsers","Testing CSS Fallbacks Without an Old Browser",{"path":3160,"title":3161},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-queries-inside-css-nesting","Container Queries Inside CSS Nesting: Keeping Responses Next to the Styles They Change",{"path":3163,"title":3164},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-range-and-logic-operators","Container Query Range Syntax and Logic Operators",{"path":3166,"title":3167},"\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":3169,"title":3170},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":3172,"title":3173},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":3175,"title":3176},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fdebugging-container-queries-in-devtools","Debugging Container Queries in DevTools: Why a Rule Doesn't Match",{"path":3178,"title":3179},"\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":3181,"title":3182},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":3184,"title":3185},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":3187,"title":3188},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":3190,"title":3191},"\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":3193,"title":3194},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-auto-flow-dense-packing","grid-auto-flow: dense for Packed Layouts",{"path":3196,"title":3197},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-template-areas-responsive-layouts","Responsive Layouts With grid-template-areas: Rearranging Regions by Name",{"path":3199,"title":3200},"\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":3202,"title":3203},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":3205,"title":3206},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fmasonry-style-layouts-with-grid","Masonry-Style Layouts With the CSS That Ships Today",{"path":3208,"title":3209},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Foverlapping-elements-with-grid-stacking","Overlapping Elements With Grid Stacking: Layers Without position: absolute",{"path":3211,"title":3212},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":3214,"title":3215},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fcentering-in-css-every-method","Centering in CSS: Every Modern Method and When Each One Breaks",{"path":3217,"title":3218},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-basis-vs-width","flex-basis vs width: Which Size a Flex Item Actually Starts From",{"path":3220,"title":3221},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-grow-and-flex-shrink-explained","flex-grow and flex-shrink Explained",{"path":3223,"title":3224},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-wrap-intrinsic-responsive-rows","Breakpoint-Free Responsive Rows With flex-wrap and flex-basis",{"path":3226,"title":3227},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflexbox-gap-and-spacing","Flexbox gap vs Margins: Spacing Items Without Edge Hacks",{"path":3229,"title":3230},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns","Flexbox Layout Patterns: One-Dimensional Layout for Real Components",{"path":3232,"title":3233},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fsticky-footer-with-flexbox-and-grid","Sticky Footer With Flexbox or Grid: Pinning the Footer on Short Pages",{"path":3235,"title":3236},"\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":3238,"title":3239},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fdebugging-clamp-values","Debugging clamp(): Values That Are Ignored, Stuck or Never Fluid",{"path":3241,"title":3242},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-line-height-and-measure","Fluid Line Height and Measure: Keeping Text Readable as It Scales",{"path":3244,"title":3245},"\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":3247,"title":3248},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":3250,"title":3251},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":3253,"title":3254},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":3256,"title":3257},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ftext-wrap-balance-and-pretty","text-wrap: balance and pretty: Better Line Breaks Without Manual Breaks",{"path":3259,"title":21},"\u002Fmastering-container-queries-responsive-layouts",{"path":3261,"title":3262},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":3264,"title":3265},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fcontent-visibility-and-contain-intrinsic-size","content-visibility and contain-intrinsic-size: Rendering Only What Is Near the Screen",{"path":3267,"title":3268},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":3270,"title":3271},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Flayout-widths-with-min-max-clamp","Layout Widths With min(), max() and clamp(): Sizing Without Breakpoints",{"path":3273,"title":3274},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":3276,"title":3277},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fobject-fit-and-object-position","object-fit and object-position: Images That Fit Any Box",{"path":3279,"title":3280},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":3282,"title":3283},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":3285,"title":3286},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":3288,"title":3289},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcss-scope-for-component-styles","@scope for Component Styles: Short Selectors That Cannot Leak",{"path":3291,"title":3292},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":3294,"title":3295},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Frevert-layer-and-revert-keywords","initial, inherit, unset, revert and revert-layer: Undoing Styles Correctly",{"path":3297,"title":3298},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fwriting-a-minimal-modern-reset","Writing a Minimal Modern CSS Reset: Every Line Justified",{"path":3300,"title":3301},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fcontent-aware-card-layouts-with-has","Content-Aware Card Layouts With :has(): One Component, Many Shapes",{"path":3303,"title":3304},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fempty-and-loading-states-with-has","Empty and Loading States With ()",{"path":3306,"title":3307},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fform-validation-layouts-with-has","Form Validation Layouts With :has(): Styling Groups From Field State",{"path":3309,"title":3310},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fhas-selector-performance",":has() Selector Performance: What Is Cheap, What Is Not, and How to Measure",{"path":3312,"title":3313},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fhas-vs-container-style-queries",":has() vs Container Style Queries: Discovered State and Published State",{"path":3315,"title":3316},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has","Parent-Aware Layouts With :has(): Letting Containers React to Their Contents",{"path":3318,"title":3319},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fquantity-queries-with-has","Quantity Queries With :has(): Layouts That Respond to How Many Items There Are",{"path":3321,"title":3322},"\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":3324,"title":3325},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":3327,"title":3328},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":3330,"title":3331},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":3333,"title":3334},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":3336,"title":3337},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-hero-sections-with-container-queries","Responsive Hero Sections With Container Queries",{"path":3339,"title":3340},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":3342,"title":3343},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-pricing-tables","Responsive Pricing Tables: Aligned Features, a Clear Recommendation, Any Width",{"path":3345,"title":3346},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Ftabs-that-become-accordions","Tabs That Become an Accordion: One Component, Two Layouts",{"path":3348,"title":3349},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap","A CSS-Only Carousel With Scroll Snap",{"path":3351,"title":3352},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fhorizontal-scrolling-card-rows","Horizontal Scrolling Card Rows: Swipeable Lists That Stay in Their Lane",{"path":3354,"title":3355},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts","Scroll Snap & Overflow Layouts: Designing Components That Scroll on Purpose",{"path":3357,"title":3358},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Foverscroll-behavior-for-nested-scrolling","overscroll-behavior: Taming Nested Scrolling, Pull-to-Refresh and Back-Swipe",{"path":3360,"title":3361},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fscroll-margin-and-scroll-padding-for-sticky-headers","scroll-margin and scroll-padding: Keeping Targets Clear of Sticky Headers",{"path":3363,"title":3364},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcombining-size-and-style-queries","Combining Size and Style Container Queries",{"path":3366,"title":3367},"\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":3369,"title":3370},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":3372,"title":3373},"\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":3375,"title":3376},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-component-variants","Component Variants With Style Queries: One Token, Many Looks",{"path":3378,"title":3379},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-fallbacks-and-support","Style Query Fallbacks and Support: Designing for Older Browser Versions",{"path":3381,"title":3382},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fdvh-svh-lvh-mobile-viewport-units","dvh, svh and lvh: Choosing the Right Mobile Viewport Unit",{"path":3384,"title":3385},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Ffull-bleed-sections-in-constrained-layouts","Full-Bleed Sections in a Constrained Layout: Breaking Out Without Breaking the Page",{"path":2833,"title":5},{"path":3388,"title":3389},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fsafe-area-insets-for-notched-screens","Safe Area Insets: Designing Around Notches, Corners and Home Indicators",{"path":3391,"title":3392},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fviewport-units-vs-container-units","Viewport Units vs Container Units: Choosing the Right Reference Box",{"path":3394,"title":3395},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fvirtual-keyboard-and-interactive-widget","Layouts That Survive the Virtual Keyboard",1789717745489]