[{"data":1,"prerenderedAt":3037},["ShallowReactive",2],{"page-\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts":3,"content-all-pages":2473,"live-demo:snap-table-scroller":3031},{"id":4,"title":5,"body":6,"description":2451,"extension":2452,"meta":2453,"navigation":787,"path":2469,"seo":2470,"stem":2471,"__hash__":2472},"content\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Findex.md","Scroll Snap & Overflow Layouts: Designing Components That Scroll on Purpose",{"type":7,"value":8,"toc":2427},"minimark",[9,13,41,47,76,79,84,118,138,239,261,268,274,361,375,377,381,656,659,661,665,668,672,747,750,754,834,844,848,910,914,957,1000,1004,1036,1039,1041,1045,1052,1341,1345,1744,1758,1760,1764,1767,1783,1792,1809,1879,1883,1889,1899,1912,1921,1925,1928,1934,1940,1946,1952,1958,1967,1969,1973,1984,1990,1999,2013,2019,2021,2025,2086,2088,2092,2201,2210,2212,2216,2302,2304,2308,2333,2341,2358,2364,2384,2388,2423],[10,11,5],"h1",{"id":12},"scroll-snap-overflow-layouts-designing-components-that-scroll-on-purpose",[14,15,16,17,21,22,27,28,32,33,36,37,40],"p",{},"Most layout guidance treats scrolling as something that happens to a page. A growing class of components scrolls ",[18,19,20],"em",{},"by design",": carousels, horizontally scrolling shelves, chat logs, dropdown lists, bottom sheets, data tables too wide for a phone, story-style full-screen sections. These components need the browser's native scrolling — its momentum, keyboard support, compositor smoothness and accessibility — and a few CSS controls over where scrolling stops, what it avoids and where it hands off. This guide, part of ",[23,24,26],"a",{"href":25},"\u002Fmastering-container-queries-responsive-layouts\u002F","Mastering Container Queries & Responsive Layouts",", explains scroll containers, CSS Scroll Snap, the snapport that ",[29,30,31],"code",{},"scroll-padding"," and ",[29,34,35],{},"scroll-margin"," shape, and the boundary behaviour controlled by ",[29,38,39],{},"overscroll-behavior",".",[14,42,43],{},[44,45,46],"strong",{},"Prerequisites — this guide assumes you can already:",[48,49,50,54,62,69],"ul",{},[51,52,53],"li",{},"Explain the difference between content overflowing a box and the box scrolling.",[51,55,56,57,61],{},"Build horizontal rows with flexbox or grid (see ",[23,58,60],{"href":59},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002F","Flexbox Layout Patterns",").",[51,63,64,65,68],{},"Use ",[29,66,67],{},"position: sticky"," for headers.",[51,70,71,72,40],{},"Write a basic ",[23,73,75],{"href":74},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002F","container query",[77,78],"hr",{},[80,81,83],"h2",{"id":82},"the-core-concept-the-scroll-container-and-its-snapport","The Core Concept: The Scroll Container and Its Snapport",[14,85,86,87,90,91,94,95,98,99,102,103,106,107,110,111,114,115,40],{},"A ",[44,88,89],{},"scroll container"," is any element whose ",[29,92,93],{},"overflow"," in an axis is ",[29,96,97],{},"auto",", ",[29,100,101],{},"scroll"," or ",[29,104,105],{},"hidden",". It clips its content to its padding box and establishes a ",[18,108,109],{},"scrollport"," — the visible window onto its scrollable overflow. The root element is the document's scroll container, which is why page-level scroll properties go on ",[29,112,113],{},"html",", not ",[29,116,117],{},"body",[14,119,120,121,124,125,128,129,131,132,134,135,137],{},"Every scroll-into-view operation in a browser — fragment links, focus changes, ",[29,122,123],{},"scrollIntoView()",", find-in-page, and snap settling — aligns a target against the scroll container's ",[44,126,127],{},"snapport",": the scrollport inset by ",[29,130,31],{},". Targets can enlarge their own alignment box with ",[29,133,35],{},". And when a scroll gesture reaches the edge of a container, ",[29,136,39],{}," decides whether the leftover movement chains to an ancestor.",[139,140,146,147,146,151,146,155,146,163,146,173,146,180,146,188,146,193,146,200,146,204,146,209,146,216,146,221,146,226,146,231,146,234],"svg",{"viewBox":141,"role":142,"ariaLabel":143,"xmlns":144,"style":145},"0 0 720 340","img","Anatomy of a scroll container: scrollable overflow, scrollport, snapport inset by scroll-padding, a target with scroll-margin, and the overscroll boundary","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[148,149,150],"title",{},"Anatomy of a scroll container",[152,153,154],"desc",{},"A long strip of scrollable overflow passes behind a scrollport window. Inside the scrollport a smaller snapport is inset by scroll-padding. A target element with a scroll-margin band aligns to the snapport's start. At the edges, overscroll-behavior governs what happens when scrolling continues.",[156,157,162],"text",{"textAnchor":158,"x":159,"y":160,"style":161},"middle","360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","Four boxes decide where scrolling stops",[164,165],"rect",{"x":166,"y":167,"width":168,"height":169,"rx":170,"fill":171,"opacity":172},"30","100","660","120","8","#7aa2ff","0.1",[156,174,179],{"textAnchor":175,"x":176,"y":177,"style":178},"start","60","94","text-anchor:start;fill:currentColor;font:12px sans-serif","scrollable overflow (all the content)",[181,182],"path",{"d":183,"fill":184,"stroke":185,"strokeWidth":186,"opacity":187},"M200 70 H520 V250 H200 Z","none","currentColor","2.5","0.8",[156,189,192],{"textAnchor":158,"x":159,"y":190,"style":191},"64","text-anchor:middle;fill:currentColor;font:600 12px sans-serif","scrollport (visible window)",[181,194],{"d":195,"stroke":171,"strokeWidth":196,"strokeDashArray":197},"M232 78 V242","3",[198,199],"6","4",[181,201],{"d":202,"stroke":171,"strokeWidth":196,"strokeDashArray":203},"M488 78 V242",[198,199],[156,205,208],{"textAnchor":158,"x":159,"y":206,"style":207},"272","text-anchor:middle;fill:currentColor;font:12px sans-serif","snapport = scrollport minus scroll-padding",[164,210],{"x":211,"y":212,"width":213,"height":214,"rx":198,"fill":171,"opacity":215},"236","124","170","72","0.45",[156,217,220],{"textAnchor":158,"x":218,"y":219,"style":191},"321","156","snap target",[156,222,225],{"textAnchor":158,"x":218,"y":223,"style":224},"176","text-anchor:middle;fill:currentColor;font:11px ui-monospace,monospace","scroll-snap-align",[156,227,39],{"textAnchor":158,"x":228,"y":229,"style":230},"110","300","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace",[156,232,39],{"textAnchor":158,"x":233,"y":229,"style":230},"610",[156,235,238],{"textAnchor":158,"x":159,"y":236,"style":237},"324","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.75","…applies at both ends, deciding whether leftover scroll chains outward.",[14,240,241,242,32,246,250,251,255,256,260],{},"Each guide in this section works with one part of that picture. ",[23,243,245],{"href":244},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap\u002F","CSS-Only Carousel With Scroll Snap",[23,247,249],{"href":248},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fhorizontal-scrolling-card-rows\u002F","Horizontal Scrolling Card Rows"," use snap targets and the snapport. ",[23,252,254],{"href":253},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fscroll-margin-and-scroll-padding-for-sticky-headers\u002F","scroll-margin and scroll-padding for Sticky Headers"," shapes the snapport for fragment and focus navigation. ",[23,257,259],{"href":258},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Foverscroll-behavior-for-nested-scrolling\u002F","overscroll-behavior for Nested Scrolling"," governs the boundaries.",[262,263,265,267],"h3",{"id":264},"overflow-values-and-what-they-create",[29,266,93],{}," values and what they create",[14,269,270,271,273],{},"The five ",[29,272,93],{}," values are not a scale from \"less\" to \"more\" clipping; they differ in whether a scroll container exists at all, and that decides everything downstream.",[139,275,146,278,146,281,146,284,146,287,146,293,146,296,146,299,146,303,146,306,146,310,146,316,146,319,146,321,146,323,146,327,146,329,146,331,146,333,146,335,146,338,146,340,146,342,146,345,146,347,146,350,146,352,146,355,146,357,146,359],{"viewBox":276,"role":142,"ariaLabel":277,"xmlns":144,"style":145},"0 0 720 280","Table of overflow values showing which create a scroll container, which show scrollbars, and which break sticky descendants",[148,279,280],{},"What each overflow value creates",[152,282,283],{},"visible and clip create no scroll container; hidden, auto and scroll do. Only auto and scroll let the user scroll. hidden, auto and scroll all become the reference for sticky descendants; clip and visible do not.",[156,285,286],{"textAnchor":158,"x":159,"y":160,"style":161},"Only some values create a scroll container",[164,288],{"x":289,"y":290,"width":291,"height":166,"rx":198,"fill":171,"opacity":292},"200","44","160","0.3",[156,294,89],{"textAnchor":158,"x":295,"y":190,"style":191},"280",[164,297],{"x":298,"y":290,"width":291,"height":166,"rx":198,"fill":171,"opacity":292},"370",[156,300,302],{"textAnchor":158,"x":301,"y":190,"style":191},"450","user can scroll",[164,304],{"x":305,"y":290,"width":291,"height":166,"rx":198,"fill":171,"opacity":292},"540",[156,307,309],{"textAnchor":158,"x":308,"y":190,"style":191},"620","sticky reference",[156,311,315],{"textAnchor":175,"x":312,"y":313,"style":314},"40","104","text-anchor:start;fill:currentColor;font:13px ui-monospace,monospace","visible",[156,317,318],{"textAnchor":158,"x":295,"y":313,"style":207},"no",[156,320,318],{"textAnchor":158,"x":301,"y":313,"style":207},[156,322,318],{"textAnchor":158,"x":308,"y":313,"style":207},[156,324,326],{"textAnchor":175,"x":312,"y":325,"style":314},"140","clip",[156,328,318],{"textAnchor":158,"x":295,"y":325,"style":207},[156,330,318],{"textAnchor":158,"x":301,"y":325,"style":207},[156,332,318],{"textAnchor":158,"x":308,"y":325,"style":207},[156,334,105],{"textAnchor":175,"x":312,"y":223,"style":314},[156,336,337],{"textAnchor":158,"x":295,"y":223,"style":191},"yes",[156,339,318],{"textAnchor":158,"x":301,"y":223,"style":207},[156,341,337],{"textAnchor":158,"x":308,"y":223,"style":191},[156,343,97],{"textAnchor":175,"x":312,"y":344,"style":314},"212",[156,346,337],{"textAnchor":158,"x":295,"y":344,"style":191},[156,348,349],{"textAnchor":158,"x":301,"y":344,"style":191},"if overflowing",[156,351,337],{"textAnchor":158,"x":308,"y":344,"style":191},[156,353,101],{"textAnchor":175,"x":312,"y":354,"style":314},"248",[156,356,337],{"textAnchor":158,"x":295,"y":354,"style":191},[156,358,337],{"textAnchor":158,"x":301,"y":354,"style":191},[156,360,337],{"textAnchor":158,"x":308,"y":354,"style":191},[14,362,363,364,366,367,370,371,374],{},"The ",[29,365,105],{}," row is the one that causes trouble. Developers add ",[29,368,369],{},"overflow: hidden"," to clip a decorative shape or contain a float, and silently create a scroll container that becomes the reference for every sticky descendant — which then never sticks, because the hidden container never scrolls. ",[29,372,373],{},"overflow: clip"," was added precisely for \"cut this off without making it scrollable\", and it should be the default choice for purely visual clipping.",[77,376],{},[80,378,380],{"id":379},"syntax-and-parameters","Syntax and Parameters",[382,383,384,403],"table",{},[385,386,387],"thead",{},[388,389,390,394,397,400],"tr",{},[391,392,393],"th",{},"Property",[391,395,396],{},"Accepted values",[391,398,399],{},"Default",[391,401,402],{},"Applies to",[404,405,406,438,479,505,526,546,565,586,606,629],"tbody",{},[388,407,408,419,431,435],{},[409,410,411,98,413,98,416],"td",{},[29,412,93],{},[29,414,415],{},"overflow-x",[29,417,418],{},"overflow-y",[409,420,421,98,423,98,425,98,427,98,429],{},[29,422,315],{},[29,424,105],{},[29,426,326],{},[29,428,101],{},[29,430,97],{},[409,432,433],{},[29,434,315],{},[409,436,437],{},"any block container",[388,439,440,445,473,477],{},[409,441,442],{},[29,443,444],{},"scroll-snap-type",[409,446,447,449,450,453,454,453,457,453,460,453,463,466,467,453,470],{},[29,448,184],{},", or ",[29,451,452],{},"x","\u002F",[29,455,456],{},"y",[29,458,459],{},"block",[29,461,462],{},"inline",[29,464,465],{},"both"," + ",[29,468,469],{},"mandatory",[29,471,472],{},"proximity",[409,474,475],{},[29,476,184],{},[409,478,89],{},[388,480,481,485,498,502],{},[409,482,483],{},[29,484,225],{},[409,486,487,98,489,98,491,98,494,497],{},[29,488,184],{},[29,490,175],{},[29,492,493],{},"end",[29,495,496],{},"center"," (one or two values)",[409,499,500],{},[29,501,184],{},[409,503,504],{},"snap targets",[388,506,507,512,520,524],{},[409,508,509],{},[29,510,511],{},"scroll-snap-stop",[409,513,514,98,517],{},[29,515,516],{},"normal",[29,518,519],{},"always",[409,521,522],{},[29,523,516],{},[409,525,504],{},[388,527,528,533,540,544],{},[409,529,530,532],{},[29,531,31],{}," and longhands",[409,534,535,98,537],{},[29,536,97],{},[29,538,539],{},"\u003Clength-percentage>",[409,541,542],{},[29,543,97],{},[409,545,89],{},[388,547,548,552,557,562],{},[409,549,550,532],{},[29,551,35],{},[409,553,554],{},[29,555,556],{},"\u003Clength>",[409,558,559],{},[29,560,561],{},"0",[409,563,564],{},"any element",[388,566,567,571,580,584],{},[409,568,569,532],{},[29,570,39],{},[409,572,573,98,575,98,578],{},[29,574,97],{},[29,576,577],{},"contain",[29,579,184],{},[409,581,582],{},[29,583,97],{},[409,585,89],{},[388,587,588,593,600,604],{},[409,589,590],{},[29,591,592],{},"scroll-behavior",[409,594,595,98,597],{},[29,596,97],{},[29,598,599],{},"smooth",[409,601,602],{},[29,603,97],{},[409,605,89],{},[388,607,608,613,623,627],{},[409,609,610],{},[29,611,612],{},"scrollbar-gutter",[409,614,615,98,617,98,620],{},[29,616,97],{},[29,618,619],{},"stable",[29,621,622],{},"stable both-edges",[409,624,625],{},[29,626,97],{},[409,628,89],{},[388,630,631,640,650,654],{},[409,632,633,636,637],{},[29,634,635],{},"scrollbar-width"," \u002F ",[29,638,639],{},"scrollbar-color",[409,641,642,98,644,98,647,649],{},[29,643,97],{},[29,645,646],{},"thin",[29,648,184],{}," \u002F two colours",[409,651,652],{},[29,653,97],{},[409,655,89],{},[14,657,658],{},"Note which properties go where. Snap type, padding, overscroll and behaviour belong to the container; snap alignment, stop and margin belong to the children. Putting a container property on a child is the most common reason a snap layout does nothing.",[77,660],{},[80,662,664],{"id":663},"step-by-step-implementation-a-story-style-section-scroller","Step-by-Step Implementation: A Story-Style Section Scroller",[14,666,667],{},"Full-screen, vertically snapping sections — the format of product tours and visual stories — exercise every property in this guide.",[262,669,671],{"id":670},"step-1-make-the-right-element-the-scroller","Step 1: make the right element the scroller",[673,674,679],"pre",{"className":675,"code":676,"language":677,"meta":678,"style":678},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast",".story {\n  height: 100svh;              \u002F* stable: sections do not resize while scrolling *\u002F\n  overflow-y: auto;\n  overscroll-behavior-y: contain;\n}\n","css","",[29,680,681,694,716,729,741],{"__ignoreMap":678},[682,683,686,690],"span",{"class":684,"line":685},"line",1,[682,687,689],{"class":688},"s-5SL",".story",[682,691,693],{"class":692},"suds8"," {\n",[682,695,697,700,703,705,709,712],{"class":684,"line":696},2,[682,698,699],{"class":688},"  height",[682,701,702],{"class":692},": ",[682,704,167],{"class":688},[682,706,708],{"class":707},"sHUrx","svh",[682,710,711],{"class":692},";              ",[682,713,715],{"class":714},"sLBg1","\u002F* stable: sections do not resize while scrolling *\u002F\n",[682,717,719,722,724,726],{"class":684,"line":718},3,[682,720,721],{"class":688},"  overflow-y",[682,723,702],{"class":692},[682,725,97],{"class":688},[682,727,728],{"class":692},";\n",[682,730,732,735,737,739],{"class":684,"line":731},4,[682,733,734],{"class":688},"  overscroll-behavior-y",[682,736,702],{"class":692},[682,738,577],{"class":688},[682,740,728],{"class":692},[682,742,744],{"class":684,"line":743},5,[682,745,746],{"class":692},"}\n",[14,748,749],{},"A dedicated scroller rather than the document keeps the rest of the page — header, footer — outside the snapping region.",[262,751,753],{"id":752},"step-2-declare-snapping","Step 2: declare snapping",[673,755,757],{"className":675,"code":756,"language":677,"meta":678,"style":678},".story {\n  scroll-snap-type: y mandatory;\n}\n\n.story > section {\n  min-height: 100%;\n  scroll-snap-align: start;\n}\n",[29,758,759,765,779,783,789,802,817,829],{"__ignoreMap":678},[682,760,761,763],{"class":684,"line":685},[682,762,689],{"class":688},[682,764,693],{"class":692},[682,766,767,770,772,774,777],{"class":684,"line":696},[682,768,769],{"class":688},"  scroll-snap-type",[682,771,702],{"class":692},[682,773,456],{"class":688},[682,775,776],{"class":688}," mandatory",[682,778,728],{"class":692},[682,780,781],{"class":684,"line":718},[682,782,746],{"class":692},[682,784,785],{"class":684,"line":731},[682,786,788],{"emptyLinePlaceholder":787},true,"\n",[682,790,791,793,796,800],{"class":684,"line":743},[682,792,689],{"class":688},[682,794,795],{"class":707}," >",[682,797,799],{"class":798},"sne4z"," section",[682,801,693],{"class":692},[682,803,805,808,810,812,815],{"class":684,"line":804},6,[682,806,807],{"class":688},"  min-height",[682,809,702],{"class":692},[682,811,167],{"class":688},[682,813,814],{"class":707},"%",[682,816,728],{"class":692},[682,818,820,823,825,827],{"class":684,"line":819},7,[682,821,822],{"class":688},"  scroll-snap-align",[682,824,702],{"class":692},[682,826,175],{"class":688},[682,828,728],{"class":692},[682,830,832],{"class":684,"line":831},8,[682,833,746],{"class":692},[14,835,836,839,840,843],{},[29,837,838],{},"min-height"," rather than ",[29,841,842],{},"height"," lets a section with more content than fits grow taller; mandatory snapping still allows scrolling within an oversized section, snapping only at its edges.",[262,845,847],{"id":846},"step-3-leave-room-for-a-sticky-caption-bar","Step 3: leave room for a sticky caption bar",[673,849,851],{"className":675,"code":850,"language":677,"meta":678,"style":678},".story { scroll-padding-top: 3rem; }\n.story__bar { position: sticky; top: 0; height: 3rem; }\n",[29,852,853,873],{"__ignoreMap":678},[682,854,855,857,860,863,865,867,870],{"class":684,"line":685},[682,856,689],{"class":688},[682,858,859],{"class":692}," { ",[682,861,862],{"class":688},"scroll-padding-top",[682,864,702],{"class":692},[682,866,196],{"class":688},[682,868,869],{"class":707},"rem",[682,871,872],{"class":692},"; }\n",[682,874,875,878,880,883,885,888,891,894,896,898,900,902,904,906,908],{"class":684,"line":696},[682,876,877],{"class":688},".story__bar",[682,879,859],{"class":692},[682,881,882],{"class":688},"position",[682,884,702],{"class":692},[682,886,887],{"class":688},"sticky",[682,889,890],{"class":692},"; ",[682,892,893],{"class":688},"top",[682,895,702],{"class":692},[682,897,561],{"class":688},[682,899,890],{"class":692},[682,901,842],{"class":688},[682,903,702],{"class":692},[682,905,196],{"class":688},[682,907,869],{"class":707},[682,909,872],{"class":692},[262,911,913],{"id":912},"step-4-make-it-operable-from-the-keyboard","Step 4: make it operable from the keyboard",[673,915,917],{"className":675,"code":916,"language":677,"meta":678,"style":678},".story:focus-visible { outline: 2px solid #2563eb; outline-offset: -2px; }\n",[29,918,919],{"__ignoreMap":678},[682,920,921,924,926,929,931,934,937,940,943,945,948,950,953,955],{"class":684,"line":685},[682,922,923],{"class":688},".story:focus-visible",[682,925,859],{"class":692},[682,927,928],{"class":688},"outline",[682,930,702],{"class":692},[682,932,933],{"class":688},"2",[682,935,936],{"class":707},"px",[682,938,939],{"class":688}," solid",[682,941,942],{"class":688}," #2563eb",[682,944,890],{"class":692},[682,946,947],{"class":688},"outline-offset",[682,949,702],{"class":692},[682,951,952],{"class":688},"-2",[682,954,936],{"class":707},[682,956,872],{"class":692},[673,958,961],{"className":959,"code":960,"language":113,"meta":678,"style":678},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cdiv class=\"story\" tabindex=\"0\" aria-label=\"Product tour, scroll to advance\">\n",[29,962,963],{"__ignoreMap":678},[682,964,965,968,971,974,977,981,984,986,989,992,994,997],{"class":684,"line":685},[682,966,967],{"class":692},"\u003C",[682,969,970],{"class":798},"div",[682,972,973],{"class":688}," class",[682,975,976],{"class":692},"=",[682,978,980],{"class":979},"sT6z2","\"story\"",[682,982,983],{"class":688}," tabindex",[682,985,976],{"class":692},[682,987,988],{"class":979},"\"0\"",[682,990,991],{"class":688}," aria-label",[682,993,976],{"class":692},[682,995,996],{"class":979},"\"Product tour, scroll to advance\"",[682,998,999],{"class":692},">\n",[262,1001,1003],{"id":1002},"step-5-soften-motion-for-users-who-asked-for-less","Step 5: soften motion for users who asked for less",[673,1005,1007],{"className":675,"code":1006,"language":677,"meta":678,"style":678},"@media (prefers-reduced-motion: no-preference) {\n  .story { scroll-behavior: smooth; }\n}\n",[29,1008,1009,1017,1032],{"__ignoreMap":678},[682,1010,1011,1014],{"class":684,"line":685},[682,1012,1013],{"class":707},"@media",[682,1015,1016],{"class":692}," (prefers-reduced-motion: no-preference) {\n",[682,1018,1019,1022,1024,1026,1028,1030],{"class":684,"line":696},[682,1020,1021],{"class":688},"  .story",[682,1023,859],{"class":692},[682,1025,592],{"class":688},[682,1027,702],{"class":692},[682,1029,599],{"class":688},[682,1031,872],{"class":692},[682,1033,1034],{"class":684,"line":718},[682,1035,746],{"class":692},[14,1037,1038],{},"Smooth scrolling affects only programmatic and link-driven scrolls; gesture scrolling already follows the platform's physics.",[77,1040],{},[80,1042,1044],{"id":1043},"annotated-production-example-a-data-table-that-scrolls-in-its-own-lane","Annotated Production Example: A Data Table That Scrolls in Its Own Lane",[14,1046,1047,1048,1051],{},"Wide tables are the most common overflow component on content sites. The pattern below keeps the table in a real table layout, scrolls it horizontally inside a labelled region, pins the first column, and uses a ",[23,1049,75],{"href":1050},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables\u002F"," to drop the scroller when there is room.",[673,1053,1055],{"className":959,"code":1054,"language":113,"meta":678,"style":678},"\u003Cfigure class=\"table-wrap\">\n  \u003Cfigcaption id=\"t-cap\">Quarterly results by region\u003C\u002Ffigcaption>\n  \u003Cdiv class=\"table-scroll\" role=\"region\" aria-labelledby=\"t-cap\" tabindex=\"0\">\n    \u003Ctable>\n      \u003Cthead>\u003Ctr>\u003Cth scope=\"col\">Region\u003C\u002Fth>\u003Cth scope=\"col\">Q1\u003C\u002Fth>\u003Cth scope=\"col\">Q2\u003C\u002Fth>\u003Cth scope=\"col\">Q3\u003C\u002Fth>\u003Cth scope=\"col\">Q4\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\n      \u003Ctbody>\u003Ctr>\u003Cth scope=\"row\">North\u003C\u002Fth>\u003Ctd>1.2m\u003C\u002Ftd>\u003Ctd>1.4m\u003C\u002Ftd>\u003Ctd>1.3m\u003C\u002Ftd>\u003Ctd>1.8m\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\n    \u003C\u002Ftable>\n  \u003C\u002Fdiv>\n\u003C\u002Ffigure>\n",[29,1056,1057,1073,1096,1132,1141,1241,1313,1322,1331],{"__ignoreMap":678},[682,1058,1059,1061,1064,1066,1068,1071],{"class":684,"line":685},[682,1060,967],{"class":692},[682,1062,1063],{"class":798},"figure",[682,1065,973],{"class":688},[682,1067,976],{"class":692},[682,1069,1070],{"class":979},"\"table-wrap\"",[682,1072,999],{"class":692},[682,1074,1075,1078,1081,1084,1086,1089,1092,1094],{"class":684,"line":696},[682,1076,1077],{"class":692},"  \u003C",[682,1079,1080],{"class":798},"figcaption",[682,1082,1083],{"class":688}," id",[682,1085,976],{"class":692},[682,1087,1088],{"class":979},"\"t-cap\"",[682,1090,1091],{"class":692},">Quarterly results by region\u003C\u002F",[682,1093,1080],{"class":798},[682,1095,999],{"class":692},[682,1097,1098,1100,1102,1104,1106,1109,1112,1114,1117,1120,1122,1124,1126,1128,1130],{"class":684,"line":718},[682,1099,1077],{"class":692},[682,1101,970],{"class":798},[682,1103,973],{"class":688},[682,1105,976],{"class":692},[682,1107,1108],{"class":979},"\"table-scroll\"",[682,1110,1111],{"class":688}," role",[682,1113,976],{"class":692},[682,1115,1116],{"class":979},"\"region\"",[682,1118,1119],{"class":688}," aria-labelledby",[682,1121,976],{"class":692},[682,1123,1088],{"class":979},[682,1125,983],{"class":688},[682,1127,976],{"class":692},[682,1129,988],{"class":979},[682,1131,999],{"class":692},[682,1133,1134,1137,1139],{"class":684,"line":731},[682,1135,1136],{"class":692},"    \u003C",[682,1138,382],{"class":798},[682,1140,999],{"class":692},[682,1142,1143,1146,1148,1151,1153,1155,1157,1160,1162,1165,1168,1170,1172,1174,1176,1178,1180,1183,1185,1187,1189,1191,1193,1195,1198,1200,1202,1204,1206,1208,1210,1213,1215,1217,1219,1221,1223,1225,1228,1230,1233,1235,1237,1239],{"class":684,"line":743},[682,1144,1145],{"class":692},"      \u003C",[682,1147,385],{"class":798},[682,1149,1150],{"class":692},">\u003C",[682,1152,388],{"class":798},[682,1154,1150],{"class":692},[682,1156,391],{"class":798},[682,1158,1159],{"class":688}," scope",[682,1161,976],{"class":692},[682,1163,1164],{"class":979},"\"col\"",[682,1166,1167],{"class":692},">Region\u003C\u002F",[682,1169,391],{"class":798},[682,1171,1150],{"class":692},[682,1173,391],{"class":798},[682,1175,1159],{"class":688},[682,1177,976],{"class":692},[682,1179,1164],{"class":979},[682,1181,1182],{"class":692},">Q1\u003C\u002F",[682,1184,391],{"class":798},[682,1186,1150],{"class":692},[682,1188,391],{"class":798},[682,1190,1159],{"class":688},[682,1192,976],{"class":692},[682,1194,1164],{"class":979},[682,1196,1197],{"class":692},">Q2\u003C\u002F",[682,1199,391],{"class":798},[682,1201,1150],{"class":692},[682,1203,391],{"class":798},[682,1205,1159],{"class":688},[682,1207,976],{"class":692},[682,1209,1164],{"class":979},[682,1211,1212],{"class":692},">Q3\u003C\u002F",[682,1214,391],{"class":798},[682,1216,1150],{"class":692},[682,1218,391],{"class":798},[682,1220,1159],{"class":688},[682,1222,976],{"class":692},[682,1224,1164],{"class":979},[682,1226,1227],{"class":692},">Q4\u003C\u002F",[682,1229,391],{"class":798},[682,1231,1232],{"class":692},">\u003C\u002F",[682,1234,388],{"class":798},[682,1236,1232],{"class":692},[682,1238,385],{"class":798},[682,1240,999],{"class":692},[682,1242,1243,1245,1247,1249,1251,1253,1255,1257,1259,1262,1265,1267,1269,1271,1274,1276,1278,1280,1283,1285,1287,1289,1292,1294,1296,1298,1301,1303,1305,1307,1309,1311],{"class":684,"line":804},[682,1244,1145],{"class":692},[682,1246,404],{"class":798},[682,1248,1150],{"class":692},[682,1250,388],{"class":798},[682,1252,1150],{"class":692},[682,1254,391],{"class":798},[682,1256,1159],{"class":688},[682,1258,976],{"class":692},[682,1260,1261],{"class":979},"\"row\"",[682,1263,1264],{"class":692},">North\u003C\u002F",[682,1266,391],{"class":798},[682,1268,1150],{"class":692},[682,1270,409],{"class":798},[682,1272,1273],{"class":692},">1.2m\u003C\u002F",[682,1275,409],{"class":798},[682,1277,1150],{"class":692},[682,1279,409],{"class":798},[682,1281,1282],{"class":692},">1.4m\u003C\u002F",[682,1284,409],{"class":798},[682,1286,1150],{"class":692},[682,1288,409],{"class":798},[682,1290,1291],{"class":692},">1.3m\u003C\u002F",[682,1293,409],{"class":798},[682,1295,1150],{"class":692},[682,1297,409],{"class":798},[682,1299,1300],{"class":692},">1.8m\u003C\u002F",[682,1302,409],{"class":798},[682,1304,1232],{"class":692},[682,1306,388],{"class":798},[682,1308,1232],{"class":692},[682,1310,404],{"class":798},[682,1312,999],{"class":692},[682,1314,1315,1318,1320],{"class":684,"line":819},[682,1316,1317],{"class":692},"    \u003C\u002F",[682,1319,382],{"class":798},[682,1321,999],{"class":692},[682,1323,1324,1327,1329],{"class":684,"line":831},[682,1325,1326],{"class":692},"  \u003C\u002F",[682,1328,970],{"class":798},[682,1330,999],{"class":692},[682,1332,1334,1337,1339],{"class":684,"line":1333},9,[682,1335,1336],{"class":692},"\u003C\u002F",[682,1338,1063],{"class":798},[682,1340,999],{"class":692},[1342,1343],"live-demo",{"name":1344},"snap-table-scroller",[673,1346,1348],{"className":675,"code":1347,"language":677,"meta":678,"style":678},".table-wrap { container-type: inline-size; margin: 0; }\n\n.table-scroll {\n  overflow-x: auto;\n  overscroll-behavior-x: contain;        \u002F* no accidental back-swipe *\u002F\n  scrollbar-gutter: stable;              \u002F* no layout jump when it appears *\u002F\n}\n\n.table-scroll:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }\n\ntable {\n  border-collapse: separate;             \u002F* sticky cells need separate borders *\u002F\n  border-spacing: 0;\n  min-width: 36rem;                      \u002F* scroll rather than crush the columns *\u002F\n  font-variant-numeric: tabular-nums;    \u002F* figures line up down each column *\u002F\n}\n\nth, td { padding: 0.5rem 0.75rem; border-bottom: 1px solid #e2e8f0; text-align: end; }\n\n\u002F* Pin the row headers so values stay labelled while scrolling. *\u002F\ntbody th, thead th:first-child {\n  position: sticky;\n  inset-inline-start: 0;\n  background: #ffffff;\n  text-align: start;\n}\n\n\u002F* Enough room: no scroller needed at all. *\u002F\n@container (width > 40rem) {\n  .table-scroll { overflow-x: visible; }\n  table { width: 100%; }\n}\n",[29,1349,1350,1372,1376,1383,1394,1409,1420,1424,1428,1459,1464,1471,1488,1500,1519,1536,1541,1546,1600,1605,1611,1630,1642,1654,1667,1679,1684,1689,1695,1704,1720,1739],{"__ignoreMap":678},[682,1351,1352,1355,1357,1360,1363,1366,1368,1370],{"class":684,"line":685},[682,1353,1354],{"class":688},".table-wrap",[682,1356,859],{"class":692},[682,1358,1359],{"class":688},"container-type",[682,1361,1362],{"class":692},": inline-size; ",[682,1364,1365],{"class":688},"margin",[682,1367,702],{"class":692},[682,1369,561],{"class":688},[682,1371,872],{"class":692},[682,1373,1374],{"class":684,"line":696},[682,1375,788],{"emptyLinePlaceholder":787},[682,1377,1378,1381],{"class":684,"line":718},[682,1379,1380],{"class":688},".table-scroll",[682,1382,693],{"class":692},[682,1384,1385,1388,1390,1392],{"class":684,"line":731},[682,1386,1387],{"class":688},"  overflow-x",[682,1389,702],{"class":692},[682,1391,97],{"class":688},[682,1393,728],{"class":692},[682,1395,1396,1399,1401,1403,1406],{"class":684,"line":743},[682,1397,1398],{"class":688},"  overscroll-behavior-x",[682,1400,702],{"class":692},[682,1402,577],{"class":688},[682,1404,1405],{"class":692},";        ",[682,1407,1408],{"class":714},"\u002F* no accidental back-swipe *\u002F\n",[682,1410,1411,1414,1417],{"class":684,"line":804},[682,1412,1413],{"class":688},"  scrollbar-gutter",[682,1415,1416],{"class":692},": stable;              ",[682,1418,1419],{"class":714},"\u002F* no layout jump when it appears *\u002F\n",[682,1421,1422],{"class":684,"line":819},[682,1423,746],{"class":692},[682,1425,1426],{"class":684,"line":831},[682,1427,788],{"emptyLinePlaceholder":787},[682,1429,1430,1433,1435,1437,1439,1441,1443,1445,1447,1449,1451,1453,1455,1457],{"class":684,"line":1333},[682,1431,1432],{"class":688},".table-scroll:focus-visible",[682,1434,859],{"class":692},[682,1436,928],{"class":688},[682,1438,702],{"class":692},[682,1440,933],{"class":688},[682,1442,936],{"class":707},[682,1444,939],{"class":688},[682,1446,942],{"class":688},[682,1448,890],{"class":692},[682,1450,947],{"class":688},[682,1452,702],{"class":692},[682,1454,933],{"class":688},[682,1456,936],{"class":707},[682,1458,872],{"class":692},[682,1460,1462],{"class":684,"line":1461},10,[682,1463,788],{"emptyLinePlaceholder":787},[682,1465,1467,1469],{"class":684,"line":1466},11,[682,1468,382],{"class":798},[682,1470,693],{"class":692},[682,1472,1474,1477,1479,1482,1485],{"class":684,"line":1473},12,[682,1475,1476],{"class":688},"  border-collapse",[682,1478,702],{"class":692},[682,1480,1481],{"class":688},"separate",[682,1483,1484],{"class":692},";             ",[682,1486,1487],{"class":714},"\u002F* sticky cells need separate borders *\u002F\n",[682,1489,1491,1494,1496,1498],{"class":684,"line":1490},13,[682,1492,1493],{"class":688},"  border-spacing",[682,1495,702],{"class":692},[682,1497,561],{"class":688},[682,1499,728],{"class":692},[682,1501,1503,1506,1508,1511,1513,1516],{"class":684,"line":1502},14,[682,1504,1505],{"class":688},"  min-width",[682,1507,702],{"class":692},[682,1509,1510],{"class":688},"36",[682,1512,869],{"class":707},[682,1514,1515],{"class":692},";                      ",[682,1517,1518],{"class":714},"\u002F* scroll rather than crush the columns *\u002F\n",[682,1520,1522,1525,1527,1530,1533],{"class":684,"line":1521},15,[682,1523,1524],{"class":688},"  font-variant-numeric",[682,1526,702],{"class":692},[682,1528,1529],{"class":688},"tabular-nums",[682,1531,1532],{"class":692},";    ",[682,1534,1535],{"class":714},"\u002F* figures line up down each column *\u002F\n",[682,1537,1539],{"class":684,"line":1538},16,[682,1540,746],{"class":692},[682,1542,1544],{"class":684,"line":1543},17,[682,1545,788],{"emptyLinePlaceholder":787},[682,1547,1549,1551,1553,1555,1557,1560,1562,1565,1567,1570,1572,1574,1577,1579,1582,1584,1586,1589,1591,1594,1596,1598],{"class":684,"line":1548},18,[682,1550,391],{"class":798},[682,1552,98],{"class":692},[682,1554,409],{"class":798},[682,1556,859],{"class":692},[682,1558,1559],{"class":688},"padding",[682,1561,702],{"class":692},[682,1563,1564],{"class":688},"0.5",[682,1566,869],{"class":707},[682,1568,1569],{"class":688}," 0.75",[682,1571,869],{"class":707},[682,1573,890],{"class":692},[682,1575,1576],{"class":688},"border-bottom",[682,1578,702],{"class":692},[682,1580,1581],{"class":688},"1",[682,1583,936],{"class":707},[682,1585,939],{"class":688},[682,1587,1588],{"class":688}," #e2e8f0",[682,1590,890],{"class":692},[682,1592,1593],{"class":688},"text-align",[682,1595,702],{"class":692},[682,1597,493],{"class":688},[682,1599,872],{"class":692},[682,1601,1603],{"class":684,"line":1602},19,[682,1604,788],{"emptyLinePlaceholder":787},[682,1606,1608],{"class":684,"line":1607},20,[682,1609,1610],{"class":714},"\u002F* Pin the row headers so values stay labelled while scrolling. *\u002F\n",[682,1612,1614,1616,1619,1621,1623,1625,1628],{"class":684,"line":1613},21,[682,1615,404],{"class":798},[682,1617,1618],{"class":798}," th",[682,1620,98],{"class":692},[682,1622,385],{"class":798},[682,1624,1618],{"class":798},[682,1626,1627],{"class":688},":first-child",[682,1629,693],{"class":692},[682,1631,1633,1636,1638,1640],{"class":684,"line":1632},22,[682,1634,1635],{"class":688},"  position",[682,1637,702],{"class":692},[682,1639,887],{"class":688},[682,1641,728],{"class":692},[682,1643,1645,1648,1650,1652],{"class":684,"line":1644},23,[682,1646,1647],{"class":688},"  inset-inline-start",[682,1649,702],{"class":692},[682,1651,561],{"class":688},[682,1653,728],{"class":692},[682,1655,1657,1660,1662,1665],{"class":684,"line":1656},24,[682,1658,1659],{"class":688},"  background",[682,1661,702],{"class":692},[682,1663,1664],{"class":688},"#ffffff",[682,1666,728],{"class":692},[682,1668,1670,1673,1675,1677],{"class":684,"line":1669},25,[682,1671,1672],{"class":688},"  text-align",[682,1674,702],{"class":692},[682,1676,175],{"class":688},[682,1678,728],{"class":692},[682,1680,1682],{"class":684,"line":1681},26,[682,1683,746],{"class":692},[682,1685,1687],{"class":684,"line":1686},27,[682,1688,788],{"emptyLinePlaceholder":787},[682,1690,1692],{"class":684,"line":1691},28,[682,1693,1694],{"class":714},"\u002F* Enough room: no scroller needed at all. *\u002F\n",[682,1696,1698,1701],{"class":684,"line":1697},29,[682,1699,1700],{"class":707},"@container",[682,1702,1703],{"class":692}," (width > 40rem) {\n",[682,1705,1707,1710,1712,1714,1716,1718],{"class":684,"line":1706},30,[682,1708,1709],{"class":688},"  .table-scroll",[682,1711,859],{"class":692},[682,1713,415],{"class":688},[682,1715,702],{"class":692},[682,1717,315],{"class":688},[682,1719,872],{"class":692},[682,1721,1723,1726,1728,1731,1733,1735,1737],{"class":684,"line":1722},31,[682,1724,1725],{"class":798},"  table",[682,1727,859],{"class":692},[682,1729,1730],{"class":688},"width",[682,1732,702],{"class":692},[682,1734,167],{"class":688},[682,1736,814],{"class":707},[682,1738,872],{"class":692},[682,1740,1742],{"class":684,"line":1741},32,[682,1743,746],{"class":692},[14,1745,1746,1747,1749,1750,1753,1754,1757],{},"The sticky first column works because ",[29,1748,1380],{}," is the nearest scroll container, which is exactly the element that scrolls. The ",[29,1751,1752],{},"role=\"region\""," with a label and ",[29,1755,1756],{},"tabindex=\"0\""," makes the scrolling region discoverable and keyboard-operable; axe-core flags scrollable regions that cannot receive focus, and screen-reader users benefit from hearing the caption as the region's name.",[77,1759],{},[80,1761,1763],{"id":1762},"choosing-a-snapping-strategy","Choosing a Snapping Strategy",[14,1765,1766],{},"Snapping is a strong intervention: it overrides where the user chose to stop. Used well, it makes a component feel precise; used indiscriminately, it makes a page feel like it is fighting the reader. Three questions settle most decisions.",[14,1768,1769,1772,1773,1775,1776,1779,1780,1782],{},[44,1770,1771],{},"Is each item meant to be viewed on its own?"," Slides in a carousel, panels in a story, full-screen onboarding steps: yes. Use ",[29,1774,469],{}," so a gesture always ends aligned, and consider ",[29,1777,1778],{},"scroll-snap-stop: always"," so fast flicks do not skip items. Cards in a browse shelf, rows in a list, paragraphs in an article: no. Use ",[29,1781,472],{},", or no snapping at all, so users can rest wherever they like.",[14,1784,1785,1788,1789,1791],{},[44,1786,1787],{},"Can an item be larger than the scrollport?"," If so, ",[29,1790,469],{}," snapping is still safe — the specification requires browsers to allow scrolling within a snap target that overflows the snapport, snapping only when an edge is reached — but test it with the largest real content, because a section whose bottom is unreachable is a serious bug.",[14,1793,1794,1797,1798,1801,1802,1804,1805,40],{},[44,1795,1796],{},"Does the container change size?"," A scroller sized in ",[29,1799,1800],{},"dvh"," resizes as mobile toolbars move, and each resize re-snaps the current target. That can look like the content twitching. Size snapping containers with stable units such as ",[29,1803,708],{},", as discussed in ",[23,1806,1808],{"href":1807},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fdvh-svh-lvh-mobile-viewport-units\u002F","dvh, svh and lvh",[139,1810,146,1813,146,1816,146,1819,146,1822,146,1825,146,1829,146,1832,146,1835,146,1838,146,1842,146,1844,146,1846,146,1849,146,1853,146,1857,146,1860,146,1863,146,1866,146,1869,146,1872,146,1875],{"viewBox":1811,"role":142,"ariaLabel":1812,"xmlns":144,"style":145},"0 0 720 260","Spectrum from no snapping through proximity to mandatory with snap-stop always, with example components at each point",[148,1814,1815],{},"How strongly to snap",[152,1817,1818],{},"A horizontal spectrum. At the left, no snapping suits articles and long lists. Proximity suits browse shelves. Mandatory suits carousels and story panels. Mandatory with snap-stop always suits one-item-per-gesture experiences such as onboarding.",[156,1820,1821],{"textAnchor":158,"x":159,"y":160,"style":161},"From free scrolling to one item per gesture",[684,1823],{"x1":176,"y1":228,"x2":168,"y2":228,"stroke":185,"strokeWidth":933,"opacity":1824},"0.6",[1826,1827],"circle",{"cx":1828,"cy":228,"r":170,"fill":171,"opacity":292},"90",[1826,1830],{"cx":1831,"cy":228,"r":170,"fill":171,"opacity":1564},"270",[1826,1833],{"cx":301,"cy":228,"r":170,"fill":171,"opacity":1834},"0.7",[1826,1836],{"cx":1837,"cy":228,"r":170,"fill":171},"630",[156,1839,184],{"textAnchor":158,"x":1828,"y":1840,"style":1841},"80","text-anchor:middle;fill:currentColor;font:600 12px ui-monospace,monospace",[156,1843,472],{"textAnchor":158,"x":1831,"y":1840,"style":1841},[156,1845,469],{"textAnchor":158,"x":301,"y":1840,"style":1841},[156,1847,1848],{"textAnchor":158,"x":1837,"y":1840,"style":1841},"+ stop: always",[156,1850,1852],{"textAnchor":158,"x":1828,"y":1851,"style":207},"146","articles",[156,1854,1856],{"textAnchor":158,"x":1828,"y":1855,"style":207},"166","long lists",[156,1858,1859],{"textAnchor":158,"x":1831,"y":1851,"style":207},"browse shelves",[156,1861,1862],{"textAnchor":158,"x":1831,"y":1855,"style":207},"galleries",[156,1864,1865],{"textAnchor":158,"x":301,"y":1851,"style":207},"carousels",[156,1867,1868],{"textAnchor":158,"x":301,"y":1855,"style":207},"story panels",[156,1870,1871],{"textAnchor":158,"x":1837,"y":1851,"style":207},"onboarding",[156,1873,1874],{"textAnchor":158,"x":1837,"y":1855,"style":207},"step flows",[156,1876,1878],{"textAnchor":158,"x":159,"y":1877,"style":207},"222","Move right only when each item genuinely deserves its own stop.",[80,1880,1882],{"id":1881},"integration-with-adjacent-css","Integration With Adjacent CSS",[14,1884,1885,1888],{},[44,1886,1887],{},"Container queries."," A scroller is a component like any other, and its internal layout — slide width, number of visible cards, whether it scrolls at all — should respond to its own width. The card-row guide's shelf switches from scrolling to wrapping with a single container query.",[14,1890,1891,1894,1895,1898],{},[44,1892,1893],{},"Sticky positioning."," Sticky elements are positioned relative to their nearest scroll container, so sticky table headers, sticky slide captions and sticky panel toolbars all work ",[18,1896,1897],{},"inside"," scrollers — provided no unintended scroll container sits in between.",[14,1900,1901,1904,1905,102,1908,1911],{},[44,1902,1903],{},"Scroll-driven animations."," Every scroll container exposes a scroll timeline, and every element inside it can have a view timeline. Progress indicators for a story scroller, fades for carousel slides and parallax within a panel can all be bound to the component's own scroller with ",[29,1906,1907],{},"scroll(nearest)",[29,1909,1910],{},"view()",", running on the compositor alongside the scroll itself.",[14,1913,1914,1917,1918,1920],{},[44,1915,1916],{},"Anchor positioning and popovers."," Menus and listboxes that scroll internally usually live in the top layer as popovers. Containment with ",[29,1919,39],{}," belongs on the popover's scrolling list, and the popover itself should not become an accidental sticky reference for its contents.",[80,1922,1924],{"id":1923},"testing-scroll-layouts-across-input-devices","Testing Scroll Layouts Across Input Devices",[14,1926,1927],{},"Scroll components are uniquely sensitive to the input device, because each one generates scrolling differently. A carousel that feels perfect under a finger can be awkward with a mouse wheel, which scrolls vertically by default and needs Shift held to scroll sideways. Build a small test matrix and run every scroll component through it before shipping.",[14,1929,1930,1933],{},[44,1931,1932],{},"Touch."," Flick fast and slow, and swipe diagonally. Mandatory snapping should always settle; diagonal vertical swipes over a horizontal scroller should still scroll the page.",[14,1935,1936,1939],{},[44,1937,1938],{},"Trackpad."," Two-finger horizontal gestures scroll horizontal containers directly and are the most common way desktop users meet carousels. Momentum continues after the fingers lift, so snapping must cope with long inertial scrolls.",[14,1941,1942,1945],{},[44,1943,1944],{},"Mouse wheel."," A plain wheel scrolls vertically. Horizontal-only scrollers are reachable with Shift+wheel, which few users know, so any horizontal scroller should have visible controls or at least a visible scrollbar for mouse users.",[14,1947,1948,1951],{},[44,1949,1950],{},"Keyboard."," Tab to the scroller, then use the arrow keys, Page Up and Down, Home and End. Tab onward into links inside the scroller and confirm each focused item is scrolled fully into view and not hidden behind a fade or sticky element.",[14,1953,1954,1957],{},[44,1955,1956],{},"Screen reader."," Navigate by heading or landmark into the scroller and read through it linearly. Off-screen items should be read in order; nothing should be announced that cannot be reached visually.",[14,1959,1960,1963,1964,1966],{},[44,1961,1962],{},"Zoom."," At 200% and 400%, fixed item widths in ",[29,1965,869],{}," may exceed the scroller's width. That is acceptable inside a horizontal scroller, but confirm that no page-level horizontal scrolling appears. Record the results per component so regressions are easy to spot when a later change touches spacing or item widths.",[77,1968],{},[80,1970,1972],{"id":1971},"performance-and-accessibility-notes","Performance and Accessibility Notes",[14,1974,1975,1978,1979,1983],{},[44,1976,1977],{},"Compositor scrolling."," Native scroll containers are scrolled on the compositor thread, so snap layouts stay smooth when the main thread is busy. Avoid scroll event listeners that write styles on every event; if scroll-linked visuals are needed, use ",[23,1980,1982],{"href":1981},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002F","scroll-driven animations",", which also run off the main thread.",[14,1985,1986,1989],{},[44,1987,1988],{},"Focusable scrollers."," Every scroll container whose content does not include a focusable element must itself be focusable with a visible focus style, or keyboard users cannot scroll it (WCAG 2.1.1 Keyboard).",[14,1991,1992,1995,1996,1998],{},[44,1993,1994],{},"Focus not obscured."," Sticky headers and footers can hide focused elements; ",[29,1997,31],{}," on the scroller fixes focus scrolling (WCAG 2.4.11).",[14,2000,2001,2004,2005,2008,2009,2012],{},[44,2002,2003],{},"Motion."," ",[29,2006,2007],{},"scroll-behavior: smooth"," animates long distances; gate it behind ",[29,2010,2011],{},"prefers-reduced-motion: no-preference",", and never auto-advance a carousel without a pause control (WCAG 2.2.2).",[14,2014,2015,2018],{},[44,2016,2017],{},"Reflow."," Horizontal scrolling inside a component is acceptable; horizontal scrolling of the whole page at 320 CSS pixels is not (WCAG 1.4.10). Contain overflow within the components that need it.",[77,2020],{},[80,2022,2024],{"id":2023},"devtools-debugging-workflow","DevTools Debugging Workflow",[2026,2027,2028,2040,2053,2070,2080],"ol",{},[51,2029,2030,2033,2034,2036,2037,2039],{},[44,2031,2032],{},"Find the scroll container."," Chrome and Edge show a ",[29,2035,101],{}," badge next to scroll containers in the Elements panel; Firefox marks them with a ",[29,2038,101],{}," badge too. If a sticky element does not stick, look up its ancestor chain for an unexpected badge.",[51,2041,2042,2045,2046,2049,2050,2052],{},[44,2043,2044],{},"Inspect snap points."," Chrome's ",[29,2047,2048],{},"scroll-snap"," badge on a snap container toggles an overlay showing each snap target's alignment. Use it to confirm that ",[29,2051,225],{}," is on the children, not the container.",[51,2054,2055,2058,2059,2061,2062,2064,2065,2067,2068,40],{},[44,2056,2057],{},"Check the snapport."," Select the scroller and read ",[29,2060,31],{}," in the Computed pane; a resolved value of ",[29,2063,97],{}," usually means the declaration landed on the wrong element, such as ",[29,2066,117],{}," instead of ",[29,2069,113],{},[51,2071,2072,2075,2076,2079],{},[44,2073,2074],{},"Reproduce chaining."," Scroll an inner panel to its end with a trackpad and continue; if the page moves, add ",[29,2077,2078],{},"overscroll-behavior: contain"," and repeat.",[51,2081,2082,2085],{},[44,2083,2084],{},"Keyboard test."," Tab into each scroller and use arrow keys and Page Down. Confirm snapping applies and the focus ring is visible.",[77,2087],{},[80,2089,2091],{"id":2090},"browser-compatibility","Browser Compatibility",[382,2093,2094,2110],{},[385,2095,2096],{},[388,2097,2098,2101,2104,2107],{},[391,2099,2100],{},"Feature",[391,2102,2103],{},"Chrome \u002F Edge",[391,2105,2106],{},"Firefox",[391,2108,2109],{},"Safari",[404,2111,2112,2133,2147,2159,2174,2187],{},[388,2113,2114,2126,2129,2131],{},[409,2115,2116,2117,98,2119,98,2122,2125],{},"CSS Scroll Snap (",[29,2118,444],{},[29,2120,2121],{},"-align",[29,2123,2124],{},"-stop",")",[409,2127,2128],{},"Supported in all current versions",[409,2130,2128],{},[409,2132,2128],{},[388,2134,2135,2141,2143,2145],{},[409,2136,2137,636,2139],{},[29,2138,31],{},[29,2140,35],{},[409,2142,2128],{},[409,2144,2128],{},[409,2146,2128],{},[388,2148,2149,2153,2155,2157],{},[409,2150,2151],{},[29,2152,39],{},[409,2154,2128],{},[409,2156,2128],{},[409,2158,2128],{},[388,2160,2161,2165,2168,2171],{},[409,2162,2163],{},[29,2164,2007],{},[409,2166,2167],{},"61+ \u002F 79+",[409,2169,2170],{},"36+",[409,2172,2173],{},"15.4+",[388,2175,2176,2180,2183,2185],{},[409,2177,2178],{},[29,2179,373],{},[409,2181,2182],{},"Supported in current versions",[409,2184,2182],{},[409,2186,2182],{},[388,2188,2189,2192,2195,2198],{},[409,2190,2191],{},"Container queries (responsive scrollers)",[409,2193,2194],{},"105+",[409,2196,2197],{},"110+",[409,2199,2200],{},"16+",[14,2202,2203,2204,2206,2207,2209],{},"Every scroll-layout property in this guide degrades safely: without snapping, a carousel is still a scrolling row; without ",[29,2205,31],{},", targets land at the very top; without ",[29,2208,39],{},", the page chains as it always did.",[77,2211],{},[80,2213,2215],{"id":2214},"common-pitfalls","Common Pitfalls",[382,2217,2218,2231],{},[385,2219,2220],{},[388,2221,2222,2225,2228],{},[391,2223,2224],{},"Pitfall",[391,2226,2227],{},"Cause",[391,2229,2230],{},"Resolution",[404,2232,2233,2246,2261,2276,2289],{},[388,2234,2235,2238,2243],{},[409,2236,2237],{},"Snap layout does nothing",[409,2239,2240,2242],{},[29,2241,225],{}," missing on children, or type on the wrong element",[409,2244,2245],{},"Type on the scroller, align on each child",[388,2247,2248,2251,2256],{},[409,2249,2250],{},"Sticky header never sticks",[409,2252,2253,2254],{},"An ancestor has ",[29,2255,369],{},[409,2257,64,2258,2260],{},[29,2259,373],{}," for visual clipping",[388,2262,2263,2266,2269],{},[409,2264,2265],{},"Anchor targets hidden under the header",[409,2267,2268],{},"Snapport ignores positioned headers",[409,2270,2271,2273,2274],{},[29,2272,862],{}," on ",[29,2275,113],{},[388,2277,2278,2281,2284],{},[409,2279,2280],{},"Page scrolls when a menu reaches its end",[409,2282,2283],{},"Scroll chaining",[409,2285,2286,2288],{},[29,2287,2078],{}," on the menu",[388,2290,2291,2294,2297],{},[409,2292,2293],{},"Scroller unreachable by keyboard",[409,2295,2296],{},"No focusable content inside",[409,2298,2299,2301],{},[29,2300,1756],{},", a label, and a focus style",[77,2303],{},[80,2305,2307],{"id":2306},"faq","FAQ",[14,2309,2310,2313,2314,2316,2317,102,2319,2321,2322,98,2325,102,2327,2329,2330,2332],{},[44,2311,2312],{},"What makes an element a scroll container?","\nAn ",[29,2315,93],{}," value other than ",[29,2318,315],{},[29,2320,326],{}," in at least one axis. ",[29,2323,2324],{},"overflow: auto",[29,2326,101],{},[29,2328,105],{}," all create a scroll container; ",[29,2331,105],{}," simply has no scrollbar and cannot be scrolled by the user, but it can still be scrolled programmatically and it still affects sticky positioning.",[14,2334,2335,2338,2339,40],{},[44,2336,2337],{},"Does scroll snap work with the keyboard?","\nYes. When a focused scroll container is scrolled with arrow keys or Page Down, the browser applies the same snap rules, so keyboard scrolling lands on snap points just like touch and wheel scrolling. The container must be focusable, which usually means adding ",[29,2340,1756],{},[14,2342,2343,2349,2350,102,2352,2354,2355,2357],{},[44,2344,2345,2346,2348],{},"Why does ",[29,2347,67],{}," stop working inside my layout?","\nSticky positioning sticks relative to the nearest scroll container ancestor. If an ancestor has ",[29,2351,369],{},[29,2353,97],{},", that ancestor becomes the reference, and if it does not itself scroll, the element never appears to stick. Remove the overflow from the ancestor or use ",[29,2356,373],{},", which does not create a scroll container.",[14,2359,2360,2363],{},[44,2361,2362],{},"Is scroll snap bad for performance?","\nNo. Snapping is applied by the browser's scrolling machinery at the end of a gesture and does not require any main-thread work from the page. Scroll-snapped layouts remain compositor-scrolled, which is why they feel smoother than script-driven carousels.",[14,2365,2366,2374,2375,2377,2378,2380,2381,2383],{},[44,2367,2368,2369,2067,2371,2373],{},"When should I use ",[29,2370,373],{},[29,2372,105],{},"?","\nUse ",[29,2376,326],{}," when you only want to cut off overflowing content visually and do not want a scroll container. ",[29,2379,326],{}," cannot be scrolled even programmatically, does not break ",[29,2382,67],{}," for descendants, and does not establish a new block formatting context.",[80,2385,2387],{"id":2386},"related","Related",[48,2389,2390,2395,2400,2405,2410,2417],{},[51,2391,2392,2394],{},[23,2393,245],{"href":244}," — one slide at a time, no script.",[51,2396,2397,2399],{},[23,2398,249],{"href":248}," — browse shelves that wrap when wide.",[51,2401,2402,2404],{},[23,2403,254],{"href":253}," — keeping targets visible.",[51,2406,2407,2409],{},[23,2408,259],{"href":258}," — stopping scroll chaining.",[51,2411,2412,2416],{},[23,2413,2415],{"href":2414},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002F","Viewport Units & Mobile Layout"," — sizing full-screen scrollers correctly.",[51,2418,2419,2422],{},[23,2420,2421],{"href":1981},"Scroll-Driven Animations"," — motion bound to the same scroll containers.",[2424,2425,2426],"style",{},"html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}",{"title":678,"searchDepth":696,"depth":696,"links":2428},[2429,2433,2434,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450],{"id":82,"depth":696,"text":83,"children":2430},[2431],{"id":264,"depth":718,"text":2432},"overflow values and what they create",{"id":379,"depth":696,"text":380},{"id":663,"depth":696,"text":664,"children":2435},[2436,2437,2438,2439,2440],{"id":670,"depth":718,"text":671},{"id":752,"depth":718,"text":753},{"id":846,"depth":718,"text":847},{"id":912,"depth":718,"text":913},{"id":1002,"depth":718,"text":1003},{"id":1043,"depth":696,"text":1044},{"id":1762,"depth":696,"text":1763},{"id":1881,"depth":696,"text":1882},{"id":1923,"depth":696,"text":1924},{"id":1971,"depth":696,"text":1972},{"id":2023,"depth":696,"text":2024},{"id":2090,"depth":696,"text":2091},{"id":2214,"depth":696,"text":2215},{"id":2306,"depth":696,"text":2307},{"id":2386,"depth":696,"text":2387},"Layouts that scroll by design: scroll containers, CSS Scroll Snap, the snapport, scroll-padding for sticky headers and overscroll-behavior for panels.","md",{"pageTitle":2454,"datePublished":2455,"dateModified":2455,"faq":2456},"Scroll Snap and Overflow Layouts in CSS","2026-09-18",[2457,2459,2461,2464,2466],{"q":2312,"a":2458},"An overflow value other than visible or clip in at least one axis. overflow: auto, scroll or hidden all create a scroll container; hidden simply has no scrollbar and cannot be scrolled by the user, but it can still be scrolled programmatically and it still affects sticky positioning.",{"q":2337,"a":2460},"Yes. When a focused scroll container is scrolled with arrow keys or Page Down, the browser applies the same snap rules, so keyboard scrolling lands on snap points just like touch and wheel scrolling. The container must be focusable, which usually means adding tabindex=\"0\".",{"q":2462,"a":2463},"Why does position: sticky stop working inside my layout?","Sticky positioning sticks relative to the nearest scroll container ancestor. If an ancestor has overflow: hidden or auto, that ancestor becomes the reference, and if it does not itself scroll, the element never appears to stick. Remove the overflow from the ancestor or use overflow: clip, which does not create a scroll container.",{"q":2362,"a":2465},"No. Snapping is applied by the browser's scrolling machinery at the end of a gesture and does not require any main-thread work from the page. Scroll-snapped layouts remain compositor-scrolled, which is why they feel smoother than script-driven carousels.",{"q":2467,"a":2468},"When should I use overflow: clip instead of hidden?","Use clip when you only want to cut off overflowing content visually and do not want a scroll container. clip cannot be scrolled even programmatically, does not break position: sticky for descendants, and does not establish a new block formatting context.","\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts",{"title":5,"description":2451},"mastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Findex","jdmtNEoJn2eskwFdOlFeb8S3ntRijr7mz_id2Tcj9XA",[2474,2477,2480,2483,2486,2489,2492,2495,2498,2501,2504,2507,2510,2513,2516,2519,2522,2525,2528,2531,2534,2537,2540,2543,2546,2549,2552,2555,2558,2561,2564,2567,2570,2573,2576,2579,2582,2585,2588,2591,2594,2597,2600,2603,2606,2609,2612,2615,2618,2621,2624,2627,2630,2633,2636,2639,2642,2645,2648,2651,2654,2657,2660,2663,2666,2669,2672,2675,2678,2681,2684,2687,2690,2693,2696,2699,2702,2705,2708,2711,2714,2717,2720,2723,2726,2729,2732,2735,2738,2741,2744,2747,2750,2753,2755,2758,2761,2764,2767,2770,2773,2776,2779,2782,2785,2788,2791,2794,2797,2800,2803,2806,2809,2812,2815,2818,2821,2824,2827,2830,2833,2836,2839,2842,2845,2848,2851,2854,2857,2860,2863,2866,2869,2872,2875,2878,2881,2884,2887,2890,2893,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,2989,2992,2995,2998,3001,3004,3007,3010,3013,3016,3019,3022,3025,3028],{"path":2475,"title":2476},"\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":2478,"title":2479},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds","Flashing Content and Seizure Thresholds",{"path":2481,"title":2482},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fforced-colors-mode-and-animations","Forced Colors Mode and Animations",{"path":2484,"title":2485},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":2487,"title":2488},"\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":2490,"title":2491},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":2493,"title":2494},"\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":2496,"title":2497},"\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":2499,"title":2500},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":2502,"title":2503},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":2505,"title":2506},"\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":2508,"title":2509},"\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":2511,"title":2512},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations","Clip-Path & Mask Animations: Animating Visibility Instead of Position",{"path":2514,"title":2515},"\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":2517,"title":2518},"\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":2520,"title":2521},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fanimating-gradients","Animating CSS Gradients: Smooth Colour Motion Without Jumps",{"path":2523,"title":2524},"\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":2526,"title":2527},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions","Color & Theme Transitions: Colour as Part of the Motion System",{"path":2529,"title":2530},"\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":2532,"title":2533},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fsmooth-theme-switching-transitions","Smooth Theme Switching: Crossfades, Circular Reveals and No Flash",{"path":2535,"title":2536},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":2538,"title":2539},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":2541,"title":2542},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Flayout-change-animations-at-container-breakpoints","Animating Changes at Container Breakpoints",{"path":2544,"title":2545},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries","Motion Driven by Container Style Queries",{"path":2547,"title":2548},"\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":2550,"title":2551},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":2553,"title":2554},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript","Controlling CSS Animations From JavaScript",{"path":2556,"title":2557},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":2559,"title":2560},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui","Interruptible UI: CSS Transitions vs WAAPI",{"path":2562,"title":2563},"\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":2565,"title":2566},"\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":2568,"title":2569},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values","Custom Property Fallbacks and Invalid Values",{"path":2571,"title":2572},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":2574,"title":2575},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":2577,"title":2578},"\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":2580,"title":2581},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components","Scoping Custom Properties to Components",{"path":2583,"title":2584},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":2586,"title":2587},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":2589,"title":2590},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions","Interrupted and Reversing Transitions: What Happens Mid-Flight",{"path":2592,"title":2593},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":2595,"title":2596},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-delay-choreography","Choreographing Motion With transition-delay",{"path":2598,"title":2599},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties","The transition Shorthand and Multiple Properties",{"path":2601,"title":2602},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":2604,"title":2605},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fanimating-dialog-open-and-close","Animating \u003Cdialog> Open and Close: Both Directions, No Library",{"path":2607,"title":2608},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fbackdrop-animations","Animating ::backdrop: Fades and Blurs Behind Dialogs and Popovers",{"path":2610,"title":2611},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations","Dialog & Popover Animations: Motion for the Top Layer",{"path":2613,"title":2614},"\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":2616,"title":2617},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fpopover-entry-and-exit-transitions","Popover Menus That Animate From Their Anchor",{"path":2619,"title":2620},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations","Choosing Animation Durations: How Long Motion Should Last",{"path":2622,"title":2623},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fcubic-bezier-overshoot-and-anticipation","Overshoot and Anticipation With cubic-bezier(): Motion With Character",{"path":2625,"title":2626},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fentry-vs-exit-easing","Entry vs Exit Easing: Different Curves for Arriving and Leaving",{"path":2628,"title":2629},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design","Easing & Motion Design: Making CSS Motion Feel Intentional",{"path":2631,"title":2632},"\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":2634,"title":2635},"\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":2637,"title":2638},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":2640,"title":2641},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fbutton-press-and-active-states","Button Press and  States",{"path":2643,"title":2644},"\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":2646,"title":2647},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":2649,"title":2650},"\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":2652,"title":2653},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":2655,"title":2656},"\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":2658,"title":2659},"\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":2661,"title":2662},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":2664,"title":2665},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-composition-and-stacking","Stacking Animations With animation-composition",{"path":2667,"title":2668},"\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":2670,"title":2671},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":2673,"title":2674},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":2676,"title":2677},"\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":2679,"title":2680},"\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":2682,"title":2683},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":2685,"title":2686},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fmulti-step-keyframes-and-per-keyframe-easing","Multi-Step Keyframes and Per-Keyframe Easing",{"path":2688,"title":2689},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":2691,"title":2692},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fanimating-box-shadow-and-filters-cheaply","Animating box-shadow and Filters Cheaply",{"path":2694,"title":2695},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcontain-property-for-animation-performance","The contain Property for Animation Performance",{"path":2697,"title":2698},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcss-triggers-layout-paint-composite","Layout, Paint and Composite: What Triggers What",{"path":2700,"title":2701},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":2703,"title":2704},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":2706,"title":2707},"\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":2709,"title":2710},"\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":2712,"title":2713},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":2715,"title":2716},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":2718,"title":2719},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-parallax-effects","Scroll-Driven Parallax Effects in CSS",{"path":2721,"title":2722},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":2724,"title":2725},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":2727,"title":2728},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Ftimeline-scope-for-cross-element-animations","timeline-scope for Cross-Element Animations",{"path":2730,"title":2731},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fview-timeline-and-animation-range","View Timelines and animation-range",{"path":2733,"title":2734},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fcross-document-view-transitions","Cross-Document View Transitions",{"path":2736,"title":2737},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":2739,"title":2740},"\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":2742,"title":2743},"\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":2745,"title":2746},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-types-and-classes","View Transition Types and Classes",{"path":2748,"title":2749},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-for-list-reordering","View Transitions for List Reordering",{"path":2751,"title":2752},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":453,"title":2754},"Modern CSS Layouts & Micro-Interactions",{"path":2756,"title":2757},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":2759,"title":2760},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":2762,"title":2763},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-size-for-matching-widths","anchor-size(): Overlays That Match Their Trigger's Size",{"path":2765,"title":2766},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":2768,"title":2769},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":2771,"title":2772},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-light-dismiss-and-stacking","Popover Light Dismiss, Nesting and Stacking",{"path":2774,"title":2775},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fposition-area-grid-explained","position-area: The Anchor Placement Grid",{"path":2777,"title":2778},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fcontainer-query-polyfill-tradeoffs","Container Query Polyfills: What They Cost and When to Skip Them",{"path":2780,"title":2781},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":2783,"title":2784},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":2786,"title":2787},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":2789,"title":2790},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fintrinsic-layout-fallbacks-without-queries","Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query",{"path":2792,"title":2793},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ftesting-fallbacks-without-old-browsers","Testing CSS Fallbacks Without an Old Browser",{"path":2795,"title":2796},"\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":2798,"title":2799},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-range-and-logic-operators","Container Query Range Syntax and Logic Operators",{"path":2801,"title":2802},"\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":2804,"title":2805},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":2807,"title":2808},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":2810,"title":2811},"\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":2813,"title":2814},"\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":2816,"title":2817},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":2819,"title":2820},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":2822,"title":2823},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":2825,"title":2826},"\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":2828,"title":2829},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-auto-flow-dense-packing","grid-auto-flow: dense for Packed Layouts",{"path":2831,"title":2832},"\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":2834,"title":2835},"\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":2837,"title":2838},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":2840,"title":2841},"\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":2843,"title":2844},"\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":2846,"title":2847},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":2849,"title":2850},"\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":2852,"title":2853},"\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":2855,"title":2856},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-grow-and-flex-shrink-explained","flex-grow and flex-shrink Explained",{"path":2858,"title":2859},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-wrap-intrinsic-responsive-rows","Breakpoint-Free Responsive Rows With flex-wrap and flex-basis",{"path":2861,"title":2862},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflexbox-gap-and-spacing","Flexbox gap vs Margins: Spacing Items Without Edge Hacks",{"path":2864,"title":2865},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns","Flexbox Layout Patterns: One-Dimensional Layout for Real Components",{"path":2867,"title":2868},"\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":2870,"title":2871},"\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":2873,"title":2874},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fdebugging-clamp-values","Debugging clamp(): Values That Are Ignored, Stuck or Never Fluid",{"path":2876,"title":2877},"\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":2879,"title":2880},"\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":2882,"title":2883},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":2885,"title":2886},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":2888,"title":2889},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":2891,"title":2892},"\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":2894,"title":26},"\u002Fmastering-container-queries-responsive-layouts",{"path":2896,"title":2897},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":2899,"title":2900},"\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":2902,"title":2903},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":2905,"title":2906},"\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":2908,"title":2909},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":2911,"title":2912},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fobject-fit-and-object-position","object-fit and object-position: Images That Fit Any Box",{"path":2914,"title":2915},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":2917,"title":2918},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":2920,"title":2921},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":2923,"title":2924},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcss-scope-for-component-styles","@scope for Component Styles: Short Selectors That Cannot Leak",{"path":2926,"title":2927},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":2929,"title":2930},"\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":2932,"title":2933},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fwriting-a-minimal-modern-reset","Writing a Minimal Modern CSS Reset: Every Line Justified",{"path":2935,"title":2936},"\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":2938,"title":2939},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fempty-and-loading-states-with-has","Empty and Loading States With ()",{"path":2941,"title":2942},"\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":2944,"title":2945},"\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":2947,"title":2948},"\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":2950,"title":2951},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has","Parent-Aware Layouts With :has(): Letting Containers React to Their Contents",{"path":2953,"title":2954},"\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":2956,"title":2957},"\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":2959,"title":2960},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":2962,"title":2963},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":2965,"title":2966},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":2968,"title":2969},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":2971,"title":2972},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-hero-sections-with-container-queries","Responsive Hero Sections With Container Queries",{"path":2974,"title":2975},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":2977,"title":2978},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-pricing-tables","Responsive Pricing Tables: Aligned Features, a Clear Recommendation, Any Width",{"path":2980,"title":2981},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Ftabs-that-become-accordions","Tabs That Become an Accordion: One Component, Two Layouts",{"path":2983,"title":2984},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap","A CSS-Only Carousel With Scroll Snap",{"path":2986,"title":2987},"\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":2469,"title":5},{"path":2990,"title":2991},"\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":2993,"title":2994},"\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":2996,"title":2997},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcombining-size-and-style-queries","Combining Size and Style Container Queries",{"path":2999,"title":3000},"\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":3002,"title":3003},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":3005,"title":3006},"\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":3008,"title":3009},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-component-variants","Component Variants With Style Queries: One Token, Many Looks",{"path":3011,"title":3012},"\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":3014,"title":3015},"\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":3017,"title":3018},"\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":3020,"title":3021},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout","Viewport Units & Mobile Layout: Designing for the Screen You Actually Get",{"path":3023,"title":3024},"\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":3026,"title":3027},"\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":3029,"title":3030},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fvirtual-keyboard-and-interactive-widget","Layouts That Survive the Virtual Keyboard",{"title":3032,"caption":3033,"height":3034,"resizable":787,"html":3035,"css":3036},"Wide table scrolling in its own region with a pinned first column","Narrow the frame and scroll the table sideways: region names stay pinned. Widen it past 40rem and the scroller disappears.",260,"\n\u003Cfigure class=\"table-wrap\">\n  \u003Cfigcaption id=\"t-cap\">Quarterly results by region\u003C\u002Ffigcaption>\n  \u003Cdiv class=\"table-scroll\" role=\"region\" aria-labelledby=\"t-cap\" tabindex=\"0\">\n    \u003Ctable>\n      \u003Cthead>\u003Ctr>\u003Cth scope=\"col\">Region\u003C\u002Fth>\u003Cth scope=\"col\">Q1\u003C\u002Fth>\u003Cth scope=\"col\">Q2\u003C\u002Fth>\u003Cth scope=\"col\">Q3\u003C\u002Fth>\u003Cth scope=\"col\">Q4\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\n      \u003Ctbody>\n        \u003Ctr>\u003Cth scope=\"row\">North\u003C\u002Fth>\u003Ctd>1.2m\u003C\u002Ftd>\u003Ctd>1.4m\u003C\u002Ftd>\u003Ctd>1.3m\u003C\u002Ftd>\u003Ctd>1.8m\u003C\u002Ftd>\u003C\u002Ftr>\n        \u003Ctr>\u003Cth scope=\"row\">South\u003C\u002Fth>\u003Ctd>0.9m\u003C\u002Ftd>\u003Ctd>1.1m\u003C\u002Ftd>\u003Ctd>1.0m\u003C\u002Ftd>\u003Ctd>1.2m\u003C\u002Ftd>\u003C\u002Ftr>\n        \u003Ctr>\u003Cth scope=\"row\">West\u003C\u002Fth>\u003Ctd>2.1m\u003C\u002Ftd>\u003Ctd>2.0m\u003C\u002Ftd>\u003Ctd>2.4m\u003C\u002Ftd>\u003Ctd>2.6m\u003C\u002Ftd>\u003C\u002Ftr>\n      \u003C\u002Ftbody>\n    \u003C\u002Ftable>\n  \u003C\u002Fdiv>\n\u003C\u002Ffigure>","\nbody { display: block; }\n.table-wrap { container-type: inline-size; margin: 0; }\nfigcaption { font-weight: 600; margin-bottom: 0.4rem; }\n.table-scroll { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-gutter: stable; }\n.table-scroll:focus-visible { outline: 2px solid var(--demo-accent); outline-offset: 2px; }\ntable { border-collapse: separate; border-spacing: 0; min-width: 36rem; font-variant-numeric: tabular-nums; }\nth, td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--demo-border); text-align: end; }\ntbody th, thead th:first-child { position: sticky; inset-inline-start: 0; background: var(--demo-bg); text-align: start; }\n@container (width > 40rem) {\n  .table-scroll { overflow-x: visible; }\n  table { width: 100%; }\n}",1789717745489]