[{"data":1,"prerenderedAt":3025},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations":3,"content-all-pages":2459,"live-demo:clip-compare-slider":3019},{"id":4,"title":5,"body":6,"description":2436,"extension":2437,"meta":2438,"navigation":908,"path":2455,"seo":2456,"stem":2457,"__hash__":2458},"content\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Findex.md","Clip-Path & Mask Animations: Animating Visibility Instead of Position",{"type":7,"value":8,"toc":2414},"minimark",[9,13,45,51,83,86,91,100,137,240,263,268,271,356,368,370,374,596,606,608,612,615,619,784,788,852,859,863,1090,1094,1143,1149,1153,1188,1191,1193,1197,1204,1208,1456,1870,1880,1882,1886,1893,1899,1905,1911,1917,1920,1924,1939,1949,1964,1974,1994,2000,2002,2006,2026,2032,2038,2048,2054,2056,2060,2100,2102,2106,2219,2226,2228,2232,2310,2312,2316,2332,2344,2356,2365,2371,2375,2411],[10,11,5],"h1",{"id":12},"clip-path-mask-animations-animating-visibility-instead-of-position",[14,15,16,17,21,22,25,26,30,31,34,35,38,39,44],"p",{},"Most CSS motion moves things: ",[18,19,20],"code",{},"transform"," slides, scales and rotates; ",[18,23,24],{},"opacity"," fades the whole element evenly. A second family of effects leaves the element exactly where it is and changes ",[27,28,29],"em",{},"which parts of it are visible",". Wipes, irises, shape morphs, soft edges, spotlights and gradient rings all belong to this family, and they are built from two properties — ",[18,32,33],{},"clip-path",", which cuts an element to a shape, and ",[18,36,37],{},"mask-image",", which sets per-pixel transparency from an image. This guide, part of ",[40,41,43],"a",{"href":42},"\u002Fcss-only-micro-interactions-animations\u002F","CSS-Only Micro-Interactions & Animations",", explains how each works, which values interpolate, what they cost to render, and how to keep them accessible.",[14,46,47],{},[48,49,50],"strong",{},"Prerequisites — this guide assumes you can already:",[52,53,54,67,70,77],"ul",{},[55,56,57,58,61,62,66],"li",{},"Write CSS transitions and ",[18,59,60],{},"@keyframes"," animations (see ",[40,63,65],{"href":64},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002F","CSS Transition Fundamentals",").",[55,68,69],{},"Use linear, radial and conic gradients as background images.",[55,71,72,73,76],{},"Register a custom property with ",[18,74,75],{},"@property",".",[55,78,79,80,76],{},"Gate motion behind ",[18,81,82],{},"prefers-reduced-motion",[84,85],"hr",{},[87,88,90],"h2",{"id":89},"the-core-concept-the-visible-region","The Core Concept: The Visible Region",[14,92,93,94,96,97,99],{},"Every rendered element has a region of pixels it paints. ",[18,95,33],{}," and ",[18,98,37],{}," both reduce that region after the element has been painted, without touching layout. The difference is in how they decide which pixels survive.",[52,101,102,130],{},[55,103,104,108,109,112,113,112,116,112,119,112,122,125,126,129],{},[48,105,106],{},[18,107,33],{}," defines a geometric shape — ",[18,110,111],{},"inset()",", ",[18,114,115],{},"circle()",[18,117,118],{},"ellipse()",[18,120,121],{},"polygon()",[18,123,124],{},"path()",", or an SVG ",[18,127,128],{},"\u003CclipPath>"," — and discards everything outside it. The boundary is hard: a pixel is either in or out. Hit testing follows the shape, so clicks outside it pass through to whatever is behind.",[55,131,132,136],{},[48,133,134],{},[18,135,37],{}," takes an image — usually a gradient — and multiplies each pixel's alpha by the mask's alpha (or luminance) at that point. The result can be partially transparent, which is how soft fades and feathered edges are made. Hit testing is not affected by a mask's transparency.",[138,139,145,146,145,150,145,154,145,162,145,180,145,189,145,195,145,202,145,209,145,213,145,216,145,220,145,224,145,228,145,231,145,236],"svg",{"viewBox":140,"role":141,"ariaLabel":142,"xmlns":143,"style":144},"0 0 720 320","img","An element passing through clip-path and mask stages: clip gives a hard-edged shape, mask gives soft partial transparency, neither moves the box","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[147,148,149],"title",{},"Where clip-path and mask act",[151,152,153],"desc",{},"An element is painted into its box. clip-path then removes everything outside a hard-edged shape. mask-image then scales each remaining pixel's alpha by the mask, creating soft edges. The layout box is unchanged throughout.",[155,156,161],"text",{"textAnchor":157,"x":158,"y":159,"style":160},"middle","360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","Paint, then clip, then mask; layout never changes",[163,164,165,166,145],"defs",{},"\n    ",[167,168,172,173,172,178,165],"linearGradient",{"id":169,"x1":170,"x2":171,"y1":170,"y2":170},"cm-soft","0","1","\n      ",[174,175],"stop",{"offset":170,"stopColor":176,"stopOpacity":177},"#7aa2ff","0.6",[174,179],{"offset":171,"stopColor":176,"stopOpacity":170},[181,182],"rect",{"x":183,"y":184,"width":185,"height":186,"rx":187,"fill":176,"opacity":188},"40","60","180","140","8","0.5",[155,190,194],{"textAnchor":157,"x":191,"y":192,"style":193},"130","228","text-anchor:middle;fill:currentColor;font:600 13px sans-serif","1. painted box",[196,197],"line",{"x1":198,"y1":191,"x2":199,"y2":191,"stroke":200,"strokeWidth":201,"opacity":177},"226","262","currentColor","2",[181,203],{"x":204,"y":184,"width":185,"height":186,"rx":187,"fill":205,"stroke":200,"strokeDashArray":206,"opacity":188},"270","none",[207,208],"5","4",[210,211],"circle",{"cx":158,"cy":191,"r":212,"fill":176,"opacity":188},"62",[155,214,215],{"textAnchor":157,"x":158,"y":192,"style":193},"2. clip-path: hard",[196,217],{"x1":218,"y1":191,"x2":219,"y2":191,"stroke":200,"strokeWidth":201,"opacity":177},"456","492",[181,221],{"x":222,"y":184,"width":185,"height":186,"rx":187,"fill":205,"stroke":200,"strokeDashArray":223,"opacity":188},"500",[207,208],[210,225],{"cx":226,"cy":191,"r":212,"fill":227},"590","url(#cm-soft)",[155,229,230],{"textAnchor":157,"x":226,"y":192,"style":193},"3. mask: soft alpha",[155,232,235],{"textAnchor":157,"x":158,"y":233,"style":234},"276","text-anchor:middle;fill:currentColor;font:12px sans-serif","The dashed outline is the unchanged layout box: nothing around it moves.",[155,237,239],{"textAnchor":157,"x":158,"y":238,"style":234},"298","Clip also governs hit testing; the mask's softness does not.",[14,241,242,243,247,248,252,253,257,258,262],{},"Because the layout box never changes, these effects are free of the problems that plague size animations: no reflow of neighbours, no layout shift, no content jumping under the reader. That makes them natural choices for entrance effects and state changes on elements whose position must stay stable. The guides in this section each take one use: ",[40,244,246],{"href":245},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fclip-path-reveal-animations\u002F","Clip-Path Reveal Animations"," for wipes and irises, ",[40,249,251],{"href":250},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fmorphing-shapes-with-clip-path-polygon\u002F","Morphing Shapes With clip-path polygon()"," for icon and badge morphs, ",[40,254,256],{"href":255},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fmask-image-fade-edges\u002F","Fade Edges With mask-image"," for soft boundaries, and ",[40,259,261],{"href":260},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Fanimated-gradient-borders-with-property\u002F","Animated Gradient Borders With @property"," for the registered-property technique that makes gradients animatable.",[264,265,267],"h3",{"id":266},"what-interpolates-and-what-does-not","What interpolates, and what does not",[14,269,270],{},"Animation depends on interpolation, and the rules differ between the two properties.",[138,272,145,275,145,278,145,281,145,284,145,291,145,298,145,303,145,308,145,311,145,315,145,318,145,321,145,323,145,327,145,329,145,332,145,335,145,339,145,341,145,343,145,346,145,350,145,353],{"viewBox":273,"role":141,"ariaLabel":274,"xmlns":143,"style":144},"0 0 720 290","Table of which clip-path and mask values interpolate directly, which need matching structure, and which need a registered property",[147,276,277],{},"Interpolation rules at a glance",[151,279,280],{},"Same-type clip shapes interpolate directly; polygons need equal point counts; path needs identical commands; mask-position and mask-size interpolate; gradient images need a registered custom property.",[155,282,283],{"textAnchor":157,"x":158,"y":159,"style":160},"Can the browser tween it?",[181,285],{"x":286,"y":287,"width":288,"height":183,"rx":289,"fill":205,"stroke":200,"strokeWidth":290,"opacity":188},"30","44","330","6","1.5",[155,292,297],{"textAnchor":293,"x":294,"y":295,"style":296},"start","46","69","text-anchor:start;fill:currentColor;font:12px ui-monospace,monospace","inset() → inset(), circle() → circle()",[181,299],{"x":300,"y":287,"width":301,"height":183,"rx":289,"fill":176,"opacity":302},"380","310","0.34",[155,304,307],{"textAnchor":157,"x":305,"y":295,"style":306},"535","text-anchor:middle;fill:currentColor;font:13px sans-serif","yes, directly",[181,309],{"x":286,"y":310,"width":288,"height":183,"rx":289,"fill":205,"stroke":200,"strokeWidth":290,"opacity":188},"92",[155,312,314],{"textAnchor":293,"x":294,"y":313,"style":296},"117","polygon() → polygon()",[181,316],{"x":300,"y":310,"width":301,"height":183,"rx":289,"fill":176,"opacity":317},"0.22",[155,319,320],{"textAnchor":157,"x":305,"y":313,"style":306},"only with equal point counts",[181,322],{"x":286,"y":186,"width":288,"height":183,"rx":289,"fill":205,"stroke":200,"strokeWidth":290,"opacity":188},[155,324,326],{"textAnchor":293,"x":294,"y":325,"style":296},"165","path() → path()",[181,328],{"x":300,"y":186,"width":301,"height":183,"rx":289,"fill":176,"opacity":317},[155,330,331],{"textAnchor":157,"x":305,"y":325,"style":306},"only with identical commands",[181,333],{"x":286,"y":334,"width":288,"height":183,"rx":289,"fill":205,"stroke":200,"strokeWidth":290,"opacity":188},"188",[155,336,338],{"textAnchor":293,"x":294,"y":337,"style":296},"213","mask-position, mask-size",[181,340],{"x":300,"y":334,"width":301,"height":183,"rx":289,"fill":176,"opacity":302},[155,342,307],{"textAnchor":157,"x":305,"y":337,"style":306},[181,344],{"x":286,"y":345,"width":288,"height":183,"rx":289,"fill":205,"stroke":200,"strokeWidth":290,"opacity":188},"236",[155,347,349],{"textAnchor":293,"x":294,"y":348,"style":296},"261","mask-image gradient stops",[181,351],{"x":300,"y":345,"width":301,"height":183,"rx":289,"fill":176,"opacity":352},"0.14",[155,354,355],{"textAnchor":157,"x":305,"y":348,"style":306},"via a registered @property",[14,357,358,359,363,364,367],{},"The bottom row is the general escape hatch. Any value that cannot interpolate as an image or shape can often be decomposed: the parts that change — an angle, a stop position, a radius — go into custom properties registered with a typed syntax, and the image or shape is rebuilt from them every frame. The ",[40,360,362],{"href":361},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fregistered-properties-and-type-safety\u002F","registered properties and type safety"," guide explains why the registration, not the ",[18,365,366],{},"var()",", is what makes this work.",[84,369],{},[87,371,373],{"id":372},"syntax-and-parameters","Syntax and Parameters",[375,376,377,396],"table",{},[378,379,380],"thead",{},[381,382,383,387,390,393],"tr",{},[384,385,386],"th",{},"Property",[384,388,389],{},"Accepted values",[384,391,392],{},"Default",[384,394,395],{},"Animatable",[397,398,399,422,447,468,487,507,534,558,579],"tbody",{},[381,400,401,406,415,419],{},[402,403,404],"td",{},[18,405,33],{},[402,407,408,410,411,414],{},[18,409,205],{},", basic shape, ",[18,412,413],{},"url(#svg-clip)",", shape with geometry box",[402,416,417],{},[18,418,205],{},[402,420,421],{},"same-type shapes",[381,423,424,428,440,444],{},[402,425,426],{},[18,427,37],{},[402,429,430,112,432,435,436,439],{},[18,431,205],{},[18,433,434],{},"\u003Cimage>"," list (gradients, ",[18,437,438],{},"url()",")",[402,441,442],{},[18,443,205],{},[402,445,446],{},"no (use a registered property)",[381,448,449,454,460,465],{},[402,450,451],{},[18,452,453],{},"mask-size",[402,455,456,457],{},"as ",[18,458,459],{},"background-size",[402,461,462],{},[18,463,464],{},"auto",[402,466,467],{},"yes",[381,469,470,475,480,485],{},[402,471,472],{},[18,473,474],{},"mask-position",[402,476,456,477],{},[18,478,479],{},"background-position",[402,481,482],{},[18,483,484],{},"0% 0%",[402,486,467],{},[381,488,489,494,499,504],{},[402,490,491],{},[18,492,493],{},"mask-repeat",[402,495,456,496],{},[18,497,498],{},"background-repeat",[402,500,501],{},[18,502,503],{},"repeat",[402,505,506],{},"no",[381,508,509,514,528,532],{},[402,510,511],{},[18,512,513],{},"mask-composite",[402,515,516,112,519,112,522,112,525],{},[18,517,518],{},"add",[18,520,521],{},"subtract",[18,523,524],{},"intersect",[18,526,527],{},"exclude",[402,529,530],{},[18,531,518],{},[402,533,506],{},[381,535,536,541,552,556],{},[402,537,538],{},[18,539,540],{},"mask-mode",[402,542,543,112,546,112,549],{},[18,544,545],{},"alpha",[18,547,548],{},"luminance",[18,550,551],{},"match-source",[402,553,554],{},[18,555,551],{},[402,557,506],{},[381,559,560,569,572,577],{},[402,561,562,565,566],{},[18,563,564],{},"mask-clip"," \u002F ",[18,567,568],{},"mask-origin",[402,570,571],{},"box keywords",[402,573,574],{},[18,575,576],{},"border-box",[402,578,506],{},[381,580,581,587,590,593],{},[402,582,583,586],{},[18,584,585],{},"mask"," (shorthand)",[402,588,589],{},"all of the above",[402,591,592],{},"—",[402,594,595],{},"per longhand",[14,597,598,599,602,603,605],{},"Basic shapes accept an optional reference box, as in ",[18,600,601],{},"clip-path: circle(50%) padding-box",", which decides the coordinate system for percentages. The default is ",[18,604,576],{},", which matches what most people expect for a clipped card.",[84,607],{},[87,609,611],{"id":610},"step-by-step-implementation-a-spotlight-that-follows-focus","Step-by-Step Implementation: A Spotlight That Follows Focus",[14,613,614],{},"The steps below build a feature grid in which the focused or hovered card is fully visible and the rest are dimmed through a mask — a spotlight effect that works with both pointer and keyboard.",[264,616,618],{"id":617},"step-1-a-grid-of-cards","Step 1: a grid of cards",[620,621,626],"pre",{"className":622,"code":623,"language":624,"meta":625,"style":625},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast",".features {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));\n  gap: 1rem;\n}\n.feature {\n  padding: 1.25rem;\n  border-radius: 12px;\n  background: #1e293b;\n  color: #f1f5f9;\n}\n","css","",[18,627,628,640,655,695,709,715,723,738,753,766,779],{"__ignoreMap":625},[629,630,632,636],"span",{"class":196,"line":631},1,[629,633,635],{"class":634},"s-5SL",".features",[629,637,639],{"class":638},"suds8"," {\n",[629,641,643,646,649,652],{"class":196,"line":642},2,[629,644,645],{"class":634},"  display",[629,647,648],{"class":638},": ",[629,650,651],{"class":634},"grid",[629,653,654],{"class":638},";\n",[629,656,658,661,663,665,668,671,673,676,678,681,685,687,689,692],{"class":196,"line":657},3,[629,659,660],{"class":634},"  grid-template-columns",[629,662,648],{"class":638},[629,664,503],{"class":634},[629,666,667],{"class":638},"(",[629,669,670],{"class":634},"auto-fill",[629,672,112],{"class":638},[629,674,675],{"class":634},"minmax",[629,677,667],{"class":638},[629,679,680],{"class":634},"12",[629,682,684],{"class":683},"sHUrx","rem",[629,686,112],{"class":638},[629,688,171],{"class":634},[629,690,691],{"class":683},"fr",[629,693,694],{"class":638},"));\n",[629,696,698,701,703,705,707],{"class":196,"line":697},4,[629,699,700],{"class":634},"  gap",[629,702,648],{"class":638},[629,704,171],{"class":634},[629,706,684],{"class":683},[629,708,654],{"class":638},[629,710,712],{"class":196,"line":711},5,[629,713,714],{"class":638},"}\n",[629,716,718,721],{"class":196,"line":717},6,[629,719,720],{"class":634},".feature",[629,722,639],{"class":638},[629,724,726,729,731,734,736],{"class":196,"line":725},7,[629,727,728],{"class":634},"  padding",[629,730,648],{"class":638},[629,732,733],{"class":634},"1.25",[629,735,684],{"class":683},[629,737,654],{"class":638},[629,739,741,744,746,748,751],{"class":196,"line":740},8,[629,742,743],{"class":634},"  border-radius",[629,745,648],{"class":638},[629,747,680],{"class":634},[629,749,750],{"class":683},"px",[629,752,654],{"class":638},[629,754,756,759,761,764],{"class":196,"line":755},9,[629,757,758],{"class":634},"  background",[629,760,648],{"class":638},[629,762,763],{"class":634},"#1e293b",[629,765,654],{"class":638},[629,767,769,772,774,777],{"class":196,"line":768},10,[629,770,771],{"class":634},"  color",[629,773,648],{"class":638},[629,775,776],{"class":634},"#f1f5f9",[629,778,654],{"class":638},[629,780,782],{"class":196,"line":781},11,[629,783,714],{"class":638},[264,785,787],{"id":786},"step-2-dim-the-cards-the-user-is-not-engaging-with","Step 2: dim the cards the user is not engaging with",[620,789,791],{"className":622,"code":790,"language":624,"meta":625,"style":625},"\u002F* When any card is hovered or focused, the others fade back. *\u002F\n.features:has(.feature:is(:hover, :focus-within)) .feature:not(:hover, :focus-within) {\n  opacity: 0.45;\n}\n",[18,792,793,799,836,848],{"__ignoreMap":625},[629,794,795],{"class":196,"line":631},[629,796,798],{"class":797},"sLBg1","\u002F* When any card is hovered or focused, the others fade back. *\u002F\n",[629,800,801,804,806,809,811,814,816,819,822,825,827,829,831,833],{"class":196,"line":642},[629,802,803],{"class":634},".features:has",[629,805,667],{"class":638},[629,807,808],{"class":634},".feature:is",[629,810,667],{"class":638},[629,812,813],{"class":634},":hover",[629,815,112],{"class":638},[629,817,818],{"class":634},":focus-within",[629,820,821],{"class":638},")) ",[629,823,824],{"class":634},".feature:not",[629,826,667],{"class":638},[629,828,813],{"class":634},[629,830,112],{"class":638},[629,832,818],{"class":634},[629,834,835],{"class":638},") {\n",[629,837,838,841,843,846],{"class":196,"line":657},[629,839,840],{"class":634},"  opacity",[629,842,648],{"class":638},[629,844,845],{"class":634},"0.45",[629,847,654],{"class":638},[629,849,850],{"class":196,"line":697},[629,851,714],{"class":638},[14,853,854,855,858],{},"A plain opacity change is the baseline; it already communicates focus and works everywhere ",[18,856,857],{},":has()"," does.",[264,860,862],{"id":861},"step-3-replace-the-flat-dim-with-a-soft-radial-mask","Step 3: replace the flat dim with a soft radial mask",[620,864,866],{"className":622,"code":865,"language":624,"meta":625,"style":625},"@property --spot {\n  syntax: \"\u003Cpercentage>\";\n  inherits: false;\n  initial-value: 0%;\n}\n\n.feature {\n  mask-image: radial-gradient(circle at 50% 40%, #000 var(--spot), rgb(0 0 0 \u002F 0.45) calc(var(--spot) + 30%));\n  --spot: 100%;\n  transition: --spot 0.35s ease;\n}\n.features:has(.feature:is(:hover, :focus-within)) .feature:not(:hover, :focus-within) {\n  --spot: 0%;\n}\n",[18,867,868,875,886,891,900,904,910,916,1004,1018,1037,1041,1072,1085],{"__ignoreMap":625},[629,869,870,872],{"class":196,"line":631},[629,871,75],{"class":683},[629,873,874],{"class":638}," --spot {\n",[629,876,877,880,883],{"class":196,"line":642},[629,878,879],{"class":638},"  syntax: \"\u003Cpercentage",[629,881,882],{"class":683},">",[629,884,885],{"class":638},"\";\n",[629,887,888],{"class":196,"line":657},[629,889,890],{"class":638},"  inherits: false;\n",[629,892,893,897],{"class":196,"line":697},[629,894,896],{"class":895},"sne4z","  initial-value",[629,898,899],{"class":638},": 0%;\n",[629,901,902],{"class":196,"line":711},[629,903,714],{"class":638},[629,905,906],{"class":196,"line":717},[629,907,909],{"emptyLinePlaceholder":908},true,"\n",[629,911,912,914],{"class":196,"line":725},[629,913,720],{"class":634},[629,915,639],{"class":638},[629,917,918,921,923,926,928,930,933,936,939,942,944,946,949,952,954,958,961,964,966,968,971,973,975,977,980,983,985,988,990,992,994,997,1000,1002],{"class":196,"line":740},[629,919,920],{"class":634},"  mask-image",[629,922,648],{"class":638},[629,924,925],{"class":634},"radial-gradient",[629,927,667],{"class":638},[629,929,210],{"class":634},[629,931,932],{"class":683}," at",[629,934,935],{"class":634}," 50",[629,937,938],{"class":683},"%",[629,940,941],{"class":634}," 40",[629,943,938],{"class":683},[629,945,112],{"class":638},[629,947,948],{"class":634},"#000",[629,950,951],{"class":634}," var",[629,953,667],{"class":638},[629,955,957],{"class":956},"soyes","--spot",[629,959,960],{"class":638},"), ",[629,962,963],{"class":634},"rgb",[629,965,667],{"class":638},[629,967,170],{"class":634},[629,969,970],{"class":634}," 0",[629,972,970],{"class":634},[629,974,565],{"class":638},[629,976,845],{"class":634},[629,978,979],{"class":638},") ",[629,981,982],{"class":634},"calc",[629,984,667],{"class":638},[629,986,987],{"class":634},"var",[629,989,667],{"class":638},[629,991,957],{"class":956},[629,993,979],{"class":638},[629,995,996],{"class":683},"+",[629,998,999],{"class":634}," 30",[629,1001,938],{"class":683},[629,1003,694],{"class":638},[629,1005,1006,1009,1011,1014,1016],{"class":196,"line":755},[629,1007,1008],{"class":956},"  --spot",[629,1010,648],{"class":638},[629,1012,1013],{"class":634},"100",[629,1015,938],{"class":683},[629,1017,654],{"class":638},[629,1019,1020,1023,1026,1029,1032,1035],{"class":196,"line":768},[629,1021,1022],{"class":634},"  transition",[629,1024,1025],{"class":638},": --spot ",[629,1027,1028],{"class":634},"0.35",[629,1030,1031],{"class":683},"s",[629,1033,1034],{"class":634}," ease",[629,1036,654],{"class":638},[629,1038,1039],{"class":196,"line":781},[629,1040,714],{"class":638},[629,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1066,1068,1070],{"class":196,"line":1043},12,[629,1045,803],{"class":634},[629,1047,667],{"class":638},[629,1049,808],{"class":634},[629,1051,667],{"class":638},[629,1053,813],{"class":634},[629,1055,112],{"class":638},[629,1057,818],{"class":634},[629,1059,821],{"class":638},[629,1061,824],{"class":634},[629,1063,667],{"class":638},[629,1065,813],{"class":634},[629,1067,112],{"class":638},[629,1069,818],{"class":634},[629,1071,835],{"class":638},[629,1073,1075,1077,1079,1081,1083],{"class":196,"line":1074},13,[629,1076,1008],{"class":956},[629,1078,648],{"class":638},[629,1080,170],{"class":634},[629,1082,938],{"class":683},[629,1084,654],{"class":638},[629,1086,1088],{"class":196,"line":1087},14,[629,1089,714],{"class":638},[264,1091,1093],{"id":1092},"step-4-keep-the-focused-cards-ring-outside-any-mask","Step 4: keep the focused card's ring outside any mask",[620,1095,1097],{"className":622,"code":1096,"language":624,"meta":625,"style":625},".feature:focus-within {\n  outline: 2px solid #93c5fd;\n  outline-offset: 3px;\n}\n",[18,1098,1099,1106,1125,1139],{"__ignoreMap":625},[629,1100,1101,1104],{"class":196,"line":631},[629,1102,1103],{"class":634},".feature:focus-within",[629,1105,639],{"class":638},[629,1107,1108,1111,1113,1115,1117,1120,1123],{"class":196,"line":642},[629,1109,1110],{"class":634},"  outline",[629,1112,648],{"class":638},[629,1114,201],{"class":634},[629,1116,750],{"class":683},[629,1118,1119],{"class":634}," solid",[629,1121,1122],{"class":634}," #93c5fd",[629,1124,654],{"class":638},[629,1126,1127,1130,1132,1135,1137],{"class":196,"line":657},[629,1128,1129],{"class":634},"  outline-offset",[629,1131,648],{"class":638},[629,1133,1134],{"class":634},"3",[629,1136,750],{"class":683},[629,1138,654],{"class":638},[629,1140,1141],{"class":196,"line":697},[629,1142,714],{"class":638},[14,1144,1145,1146,1148],{},"The focused card's ",[18,1147,957],{}," is 100%, so its mask is fully opaque and its outline shows. Only unfocused cards are masked, which is why the ring survives.",[264,1150,1152],{"id":1151},"step-5-respect-reduced-motion","Step 5: respect reduced motion",[620,1154,1156],{"className":622,"code":1155,"language":624,"meta":625,"style":625},"@media (prefers-reduced-motion: reduce) {\n  .feature { transition: none; }\n}\n",[18,1157,1158,1166,1184],{"__ignoreMap":625},[629,1159,1160,1163],{"class":196,"line":631},[629,1161,1162],{"class":683},"@media",[629,1164,1165],{"class":638}," (prefers-reduced-motion: reduce) {\n",[629,1167,1168,1171,1174,1177,1179,1181],{"class":196,"line":642},[629,1169,1170],{"class":634},"  .feature",[629,1172,1173],{"class":638}," { ",[629,1175,1176],{"class":634},"transition",[629,1178,648],{"class":638},[629,1180,205],{"class":634},[629,1182,1183],{"class":638},"; }\n",[629,1185,1186],{"class":196,"line":657},[629,1187,714],{"class":638},[14,1189,1190],{},"The dimming still happens for reduced-motion users; it simply happens instantly.",[84,1192],{},[87,1194,1196],{"id":1195},"annotated-production-example-an-image-comparison-slider","Annotated Production Example: An Image Comparison Slider",[14,1198,1199,1200,1203],{},"A before\u002Fafter slider is a clip-path classic. The version below uses a native range input for the control, so it is keyboard and screen-reader accessible, and ",[18,1201,1202],{},"clip-path: inset()"," driven by a custom property to reveal the \"after\" image. The one line of script updates the property; everything visual is CSS.",[1205,1206],"live-demo",{"name":1207},"clip-compare-slider",[620,1209,1213],{"className":1210,"code":1211,"language":1212,"meta":625,"style":625},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cfigure class=\"compare\" style=\"--pos: 50%\">\n  \u003Cdiv class=\"compare__before\" role=\"img\" aria-label=\"Kitchen before renovation\">\u003C\u002Fdiv>\n  \u003Cdiv class=\"compare__after\" role=\"img\" aria-label=\"Kitchen after renovation\">\u003C\u002Fdiv>\n  \u003Clabel class=\"compare__control\">\n    \u003Cspan class=\"visually-hidden\">Reveal amount\u003C\u002Fspan>\n    \u003Cinput type=\"range\" min=\"0\" max=\"100\" value=\"50\"\n           oninput=\"this.closest('.compare').style.setProperty('--pos', this.value + '%')\">\n  \u003C\u002Flabel>\n\u003C\u002Ffigure>\n","html",[18,1214,1215,1244,1282,1314,1330,1351,1390,1438,1447],{"__ignoreMap":625},[629,1216,1217,1220,1223,1226,1229,1233,1236,1238,1241],{"class":196,"line":631},[629,1218,1219],{"class":638},"\u003C",[629,1221,1222],{"class":895},"figure",[629,1224,1225],{"class":634}," class",[629,1227,1228],{"class":638},"=",[629,1230,1232],{"class":1231},"sT6z2","\"compare\"",[629,1234,1235],{"class":634}," style",[629,1237,1228],{"class":638},[629,1239,1240],{"class":1231},"\"--pos: 50%\"",[629,1242,1243],{"class":638},">\n",[629,1245,1246,1249,1252,1254,1256,1259,1262,1264,1267,1270,1272,1275,1278,1280],{"class":196,"line":642},[629,1247,1248],{"class":638},"  \u003C",[629,1250,1251],{"class":895},"div",[629,1253,1225],{"class":634},[629,1255,1228],{"class":638},[629,1257,1258],{"class":1231},"\"compare__before\"",[629,1260,1261],{"class":634}," role",[629,1263,1228],{"class":638},[629,1265,1266],{"class":1231},"\"img\"",[629,1268,1269],{"class":634}," aria-label",[629,1271,1228],{"class":638},[629,1273,1274],{"class":1231},"\"Kitchen before renovation\"",[629,1276,1277],{"class":638},">\u003C\u002F",[629,1279,1251],{"class":895},[629,1281,1243],{"class":638},[629,1283,1284,1286,1288,1290,1292,1295,1297,1299,1301,1303,1305,1308,1310,1312],{"class":196,"line":657},[629,1285,1248],{"class":638},[629,1287,1251],{"class":895},[629,1289,1225],{"class":634},[629,1291,1228],{"class":638},[629,1293,1294],{"class":1231},"\"compare__after\"",[629,1296,1261],{"class":634},[629,1298,1228],{"class":638},[629,1300,1266],{"class":1231},[629,1302,1269],{"class":634},[629,1304,1228],{"class":638},[629,1306,1307],{"class":1231},"\"Kitchen after renovation\"",[629,1309,1277],{"class":638},[629,1311,1251],{"class":895},[629,1313,1243],{"class":638},[629,1315,1316,1318,1321,1323,1325,1328],{"class":196,"line":697},[629,1317,1248],{"class":638},[629,1319,1320],{"class":895},"label",[629,1322,1225],{"class":634},[629,1324,1228],{"class":638},[629,1326,1327],{"class":1231},"\"compare__control\"",[629,1329,1243],{"class":638},[629,1331,1332,1335,1337,1339,1341,1344,1347,1349],{"class":196,"line":711},[629,1333,1334],{"class":638},"    \u003C",[629,1336,629],{"class":895},[629,1338,1225],{"class":634},[629,1340,1228],{"class":638},[629,1342,1343],{"class":1231},"\"visually-hidden\"",[629,1345,1346],{"class":638},">Reveal amount\u003C\u002F",[629,1348,629],{"class":895},[629,1350,1243],{"class":638},[629,1352,1353,1355,1358,1361,1363,1366,1369,1371,1374,1377,1379,1382,1385,1387],{"class":196,"line":717},[629,1354,1334],{"class":638},[629,1356,1357],{"class":895},"input",[629,1359,1360],{"class":634}," type",[629,1362,1228],{"class":638},[629,1364,1365],{"class":1231},"\"range\"",[629,1367,1368],{"class":634}," min",[629,1370,1228],{"class":638},[629,1372,1373],{"class":1231},"\"0\"",[629,1375,1376],{"class":634}," max",[629,1378,1228],{"class":638},[629,1380,1381],{"class":1231},"\"100\"",[629,1383,1384],{"class":634}," value",[629,1386,1228],{"class":638},[629,1388,1389],{"class":1231},"\"50\"\n",[629,1391,1392,1395,1397,1400,1403,1405,1409,1412,1415,1417,1420,1423,1425,1427,1430,1433,1436],{"class":196,"line":725},[629,1393,1394],{"class":634},"           oninput",[629,1396,1228],{"class":638},[629,1398,1399],{"class":1231},"\"",[629,1401,1402],{"class":634},"this",[629,1404,76],{"class":1231},[629,1406,1408],{"class":1407},"sKwhi","closest",[629,1410,1411],{"class":1231},"('.compare').",[629,1413,1414],{"class":638},"style",[629,1416,76],{"class":1231},[629,1418,1419],{"class":1407},"setProperty",[629,1421,1422],{"class":1231},"('--pos', ",[629,1424,1402],{"class":634},[629,1426,76],{"class":1231},[629,1428,1429],{"class":638},"value",[629,1431,1432],{"class":683}," +",[629,1434,1435],{"class":1231}," '%')\"",[629,1437,1243],{"class":638},[629,1439,1440,1443,1445],{"class":196,"line":740},[629,1441,1442],{"class":638},"  \u003C\u002F",[629,1444,1320],{"class":895},[629,1446,1243],{"class":638},[629,1448,1449,1452,1454],{"class":196,"line":755},[629,1450,1451],{"class":638},"\u003C\u002F",[629,1453,1222],{"class":895},[629,1455,1243],{"class":638},[620,1457,1459],{"className":622,"code":1458,"language":624,"meta":625,"style":625},".compare {\n  position: relative;\n  display: grid;\n  aspect-ratio: 16 \u002F 9;\n  margin: 0;\n  border-radius: 12px;\n  overflow: hidden;\n}\n\n\u002F* Both images occupy the same grid cell. *\u002F\n.compare__before,\n.compare__after { grid-area: 1 \u002F 1; }\n\n.compare__before { background: linear-gradient(135deg, #78716c, #44403c); }\n.compare__after  { background: linear-gradient(135deg, #fde68a, #f59e0b); }\n\n\u002F* The after image is clipped from the right: only the part left of\n   --pos is visible. inset() interpolates, so --pos could also be\n   transitioned for an animated intro. *\u002F\n.compare__after {\n  clip-path: inset(0 calc(100% - var(--pos)) 0 0);\n}\n\n\u002F* The native range input sits across the bottom as the real control. *\u002F\n.compare__control {\n  grid-area: 1 \u002F 1;\n  align-self: end;\n  padding: 0.75rem;\n}\n.compare__control input { width: 100%; accent-color: #f8fafc; }\n.compare__control input:focus-visible { outline: 2px solid #f8fafc; outline-offset: 2px; }\n",[18,1460,1461,1468,1480,1490,1507,1518,1530,1542,1546,1550,1555,1563,1583,1587,1622,1654,1659,1665,1671,1677,1684,1727,1732,1737,1743,1751,1767,1780,1794,1799,1831],{"__ignoreMap":625},[629,1462,1463,1466],{"class":196,"line":631},[629,1464,1465],{"class":634},".compare",[629,1467,639],{"class":638},[629,1469,1470,1473,1475,1478],{"class":196,"line":642},[629,1471,1472],{"class":634},"  position",[629,1474,648],{"class":638},[629,1476,1477],{"class":634},"relative",[629,1479,654],{"class":638},[629,1481,1482,1484,1486,1488],{"class":196,"line":657},[629,1483,645],{"class":634},[629,1485,648],{"class":638},[629,1487,651],{"class":634},[629,1489,654],{"class":638},[629,1491,1492,1495,1497,1500,1502,1505],{"class":196,"line":697},[629,1493,1494],{"class":634},"  aspect-ratio",[629,1496,648],{"class":638},[629,1498,1499],{"class":634},"16",[629,1501,565],{"class":638},[629,1503,1504],{"class":634},"9",[629,1506,654],{"class":638},[629,1508,1509,1512,1514,1516],{"class":196,"line":711},[629,1510,1511],{"class":634},"  margin",[629,1513,648],{"class":638},[629,1515,170],{"class":634},[629,1517,654],{"class":638},[629,1519,1520,1522,1524,1526,1528],{"class":196,"line":717},[629,1521,743],{"class":634},[629,1523,648],{"class":638},[629,1525,680],{"class":634},[629,1527,750],{"class":683},[629,1529,654],{"class":638},[629,1531,1532,1535,1537,1540],{"class":196,"line":725},[629,1533,1534],{"class":634},"  overflow",[629,1536,648],{"class":638},[629,1538,1539],{"class":634},"hidden",[629,1541,654],{"class":638},[629,1543,1544],{"class":196,"line":740},[629,1545,714],{"class":638},[629,1547,1548],{"class":196,"line":755},[629,1549,909],{"emptyLinePlaceholder":908},[629,1551,1552],{"class":196,"line":768},[629,1553,1554],{"class":797},"\u002F* Both images occupy the same grid cell. *\u002F\n",[629,1556,1557,1560],{"class":196,"line":781},[629,1558,1559],{"class":634},".compare__before",[629,1561,1562],{"class":638},",\n",[629,1564,1565,1568,1570,1573,1575,1577,1579,1581],{"class":196,"line":1043},[629,1566,1567],{"class":634},".compare__after",[629,1569,1173],{"class":638},[629,1571,1572],{"class":634},"grid-area",[629,1574,648],{"class":638},[629,1576,171],{"class":634},[629,1578,565],{"class":638},[629,1580,171],{"class":634},[629,1582,1183],{"class":638},[629,1584,1585],{"class":196,"line":1074},[629,1586,909],{"emptyLinePlaceholder":908},[629,1588,1589,1591,1593,1596,1598,1601,1603,1606,1609,1611,1614,1616,1619],{"class":196,"line":1087},[629,1590,1559],{"class":634},[629,1592,1173],{"class":638},[629,1594,1595],{"class":634},"background",[629,1597,648],{"class":638},[629,1599,1600],{"class":634},"linear-gradient",[629,1602,667],{"class":638},[629,1604,1605],{"class":634},"135",[629,1607,1608],{"class":683},"deg",[629,1610,112],{"class":638},[629,1612,1613],{"class":634},"#78716c",[629,1615,112],{"class":638},[629,1617,1618],{"class":634},"#44403c",[629,1620,1621],{"class":638},"); }\n",[629,1623,1625,1627,1630,1632,1634,1636,1638,1640,1642,1644,1647,1649,1652],{"class":196,"line":1624},15,[629,1626,1567],{"class":634},[629,1628,1629],{"class":638},"  { ",[629,1631,1595],{"class":634},[629,1633,648],{"class":638},[629,1635,1600],{"class":634},[629,1637,667],{"class":638},[629,1639,1605],{"class":634},[629,1641,1608],{"class":683},[629,1643,112],{"class":638},[629,1645,1646],{"class":634},"#fde68a",[629,1648,112],{"class":638},[629,1650,1651],{"class":634},"#f59e0b",[629,1653,1621],{"class":638},[629,1655,1657],{"class":196,"line":1656},16,[629,1658,909],{"emptyLinePlaceholder":908},[629,1660,1662],{"class":196,"line":1661},17,[629,1663,1664],{"class":797},"\u002F* The after image is clipped from the right: only the part left of\n",[629,1666,1668],{"class":196,"line":1667},18,[629,1669,1670],{"class":797},"   --pos is visible. inset() interpolates, so --pos could also be\n",[629,1672,1674],{"class":196,"line":1673},19,[629,1675,1676],{"class":797},"   transitioned for an animated intro. *\u002F\n",[629,1678,1680,1682],{"class":196,"line":1679},20,[629,1681,1567],{"class":634},[629,1683,639],{"class":638},[629,1685,1687,1690,1692,1695,1697,1699,1702,1704,1706,1708,1711,1713,1715,1718,1720,1722,1724],{"class":196,"line":1686},21,[629,1688,1689],{"class":634},"  clip-path",[629,1691,648],{"class":638},[629,1693,1694],{"class":634},"inset",[629,1696,667],{"class":638},[629,1698,170],{"class":634},[629,1700,1701],{"class":634}," calc",[629,1703,667],{"class":638},[629,1705,1013],{"class":634},[629,1707,938],{"class":683},[629,1709,1710],{"class":683}," -",[629,1712,951],{"class":634},[629,1714,667],{"class":638},[629,1716,1717],{"class":956},"--pos",[629,1719,821],{"class":638},[629,1721,170],{"class":634},[629,1723,970],{"class":634},[629,1725,1726],{"class":638},");\n",[629,1728,1730],{"class":196,"line":1729},22,[629,1731,714],{"class":638},[629,1733,1735],{"class":196,"line":1734},23,[629,1736,909],{"emptyLinePlaceholder":908},[629,1738,1740],{"class":196,"line":1739},24,[629,1741,1742],{"class":797},"\u002F* The native range input sits across the bottom as the real control. *\u002F\n",[629,1744,1746,1749],{"class":196,"line":1745},25,[629,1747,1748],{"class":634},".compare__control",[629,1750,639],{"class":638},[629,1752,1754,1757,1759,1761,1763,1765],{"class":196,"line":1753},26,[629,1755,1756],{"class":634},"  grid-area",[629,1758,648],{"class":638},[629,1760,171],{"class":634},[629,1762,565],{"class":638},[629,1764,171],{"class":634},[629,1766,654],{"class":638},[629,1768,1770,1773,1775,1778],{"class":196,"line":1769},27,[629,1771,1772],{"class":634},"  align-self",[629,1774,648],{"class":638},[629,1776,1777],{"class":634},"end",[629,1779,654],{"class":638},[629,1781,1783,1785,1787,1790,1792],{"class":196,"line":1782},28,[629,1784,728],{"class":634},[629,1786,648],{"class":638},[629,1788,1789],{"class":634},"0.75",[629,1791,684],{"class":683},[629,1793,654],{"class":638},[629,1795,1797],{"class":196,"line":1796},29,[629,1798,714],{"class":638},[629,1800,1802,1804,1807,1809,1812,1814,1816,1818,1821,1824,1826,1829],{"class":196,"line":1801},30,[629,1803,1748],{"class":634},[629,1805,1806],{"class":895}," input",[629,1808,1173],{"class":638},[629,1810,1811],{"class":634},"width",[629,1813,648],{"class":638},[629,1815,1013],{"class":634},[629,1817,938],{"class":683},[629,1819,1820],{"class":638},"; ",[629,1822,1823],{"class":634},"accent-color",[629,1825,648],{"class":638},[629,1827,1828],{"class":634},"#f8fafc",[629,1830,1183],{"class":638},[629,1832,1834,1836,1838,1841,1843,1846,1848,1850,1852,1854,1857,1859,1862,1864,1866,1868],{"class":196,"line":1833},31,[629,1835,1748],{"class":634},[629,1837,1806],{"class":895},[629,1839,1840],{"class":634},":focus-visible",[629,1842,1173],{"class":638},[629,1844,1845],{"class":634},"outline",[629,1847,648],{"class":638},[629,1849,201],{"class":634},[629,1851,750],{"class":683},[629,1853,1119],{"class":634},[629,1855,1856],{"class":634}," #f8fafc",[629,1858,1820],{"class":638},[629,1860,1861],{"class":634},"outline-offset",[629,1863,648],{"class":638},[629,1865,201],{"class":634},[629,1867,750],{"class":683},[629,1869,1183],{"class":638},[14,1871,1872,1873,1876,1877,1879],{},"The native range input carries the whole accessibility story: it is focusable, operable with arrow keys, and announced with its value. A custom draggable handle built from a ",[18,1874,1875],{},"\u003Cdiv>"," would need all of that recreated with ARIA and script. The clip follows the input's value through ",[18,1878,1717],{},", so the visual and the accessible state cannot diverge.",[84,1881],{},[87,1883,1885],{"id":1884},"choosing-between-clip-mask-opacity-and-transform","Choosing Between Clip, Mask, Opacity and Transform",[14,1887,1888,1889,1892],{},"Four properties can make something appear or disappear, and choosing well is mostly about what the effect should ",[27,1890,1891],{},"say"," and what it may cost.",[14,1894,1895,1898],{},[48,1896,1897],{},"Opacity"," says \"fading in or out\" and nothing about direction. It is composited everywhere and is the cheapest option. Use it for anything that loops, anything that appears many times on a page, and anything where direction would be meaningless — toasts, tooltips, hover states.",[14,1900,1901,1904],{},[48,1902,1903],{},"Transform"," says \"moving\" or \"growing\". It is also composited and cheap. Use it when the content genuinely travels: a drawer sliding in, a card lifting on hover. Scale transforms distort text during the animation, which is acceptable for brief motion but not for content the reader is trying to read mid-animation.",[14,1906,1907,1910],{},[48,1908,1909],{},"Clip-path"," says \"being uncovered\" and has a direction or a centre. The content is sharp and in place from the first frame, which makes it ideal for headings, images and panels whose position must stay stable. It usually repaints, so keep it short.",[14,1912,1913,1916],{},[48,1914,1915],{},"Mask"," says \"blending into its surroundings\". It is the only one of the four that can produce partial transparency across part of an element, so fades at edges, spotlights and vignettes need it. Gradient mask animations repaint every frame.",[14,1918,1919],{},"A useful rule in design reviews: if an effect can be done with opacity or transform and still communicate the same thing, do it that way. Reach for clip and mask when the uncovering or the soft edge is the point of the effect, not a stylistic flourish on something opacity could handle.",[87,1921,1923],{"id":1922},"integration-with-adjacent-css","Integration With Adjacent CSS",[14,1925,1926,1929,1930,1933,1934,1938],{},[48,1927,1928],{},"Container queries."," Clip shapes written in percentages scale with the element, which is what a responsive component wants. Where a shape needs absolute proportions — a notch of fixed depth, a corner cut of 1rem — combine percentages with ",[18,1931,1932],{},"calc()"," or ",[40,1935,1937],{"href":1936},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-units-cqi-cqb-explained\u002F","container query units"," so the geometry adapts to the component's width rather than the viewport's.",[14,1940,1941,1944,1945,1948],{},[48,1942,1943],{},"Scroll-driven animations."," Reveals are most often wanted as elements enter the viewport. A ",[18,1946,1947],{},"view()"," timeline drives a clip or mask animation directly from scroll position, with no observer script, and the same keyframes serve both time-based and scroll-based versions.",[14,1950,1951,1954,1955,96,1957,1959,1960,1963],{},[48,1952,1953],{},"View transitions."," The snapshot pseudo-elements of a view transition accept ",[18,1956,33],{},[18,1958,585],{}," like any element, so a page transition can iris or wipe from old to new content by animating ",[18,1961,1962],{},"::view-transition-new(root)"," with a clip.",[14,1965,1966,1969,1970,1973],{},[48,1967,1968],{},"Cascade layers."," Motion effects are easier to disable wholesale when they live in their own layer. A ",[18,1971,1972],{},"motion"," layer holding every clip and mask animation can be neutralised by a single reduced-motion rule in a later layer.",[14,1975,1976,1982,1983,1986,1987,1933,1990,1993],{},[48,1977,1978,1981],{},[18,1979,1980],{},"@supports"," for progressive enhancement."," Clip-path basic shapes are universal, but newer pieces — the ",[18,1984,1985],{},"shape()"," function, unprefixed mask composition in older engines, registered properties — are not. Guard them with feature queries such as ",[18,1988,1989],{},"@supports (mask-composite: intersect)",[18,1991,1992],{},"@supports (clip-path: shape(from 0 0, line to 100% 0))",", and write the unguarded rule so the element is simply visible and unmasked. An effect that fails should leave content plainly readable, never half-clipped.",[14,1995,1996,1999],{},[48,1997,1998],{},"Custom properties as the control surface."," Every example in this section exposes its moving part — a position, an angle, a radius — as a custom property. That makes the effect scriptable when needed (as in the comparison slider), themable, and trivially disabled: setting the property to its end value is the reduced-motion fallback.",[84,2001],{},[87,2003,2005],{"id":2004},"performance-and-accessibility-notes","Performance and Accessibility Notes",[14,2007,2008,2011,2012,96,2014,2016,2017,96,2019,2021,2022,76],{},[48,2009,2010],{},"Rendering cost."," ",[18,2013,20],{},[18,2015,24],{}," animations are composited by default in every engine. ",[18,2018,33],{},[18,2020,585],{}," animations are not guaranteed to be: many repaint on the main thread each frame, and gradient masks rebuilt from registered properties always repaint. Keep these effects short, limit how many run simultaneously, and profile on mid-range hardware, as described in ",[40,2023,2025],{"href":2024},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fprofiling-animations-in-devtools\u002F","Profiling Animations in DevTools",[14,2027,2028,2031],{},[48,2029,2030],{},"Clipped focus rings."," Both properties clip the element's outline and shadow. A focus indicator on a clipped element may be partly or entirely invisible. Put the ring on an unclipped wrapper, or ensure the clip is removed in the focused state.",[14,2033,2034,2037],{},[48,2035,2036],{},"Hidden content is still content."," Neither property removes content from the accessibility tree. Text clipped to nothing or masked to transparent is still read by screen readers. Use these effects only for content that is also visible in its final state.",[14,2039,2040,2043,2044,76],{},[48,2041,2042],{},"Reduced motion."," Sweeping reveals and continuous gradient rotations are exactly the motion that reduced-motion users are asking to avoid. Provide the end state instantly, following the patterns in ",[40,2045,2047],{"href":2046},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes\u002F","prefers-reduced-motion Recipes",[14,2049,2050,2053],{},[48,2051,2052],{},"Contrast at every frame."," A fade that dims text below 4.5:1 contrast is acceptable only for content the user is not currently meant to read. Check the final, resting state for contrast, not just the start.",[84,2055],{},[87,2057,2059],{"id":2058},"devtools-debugging-workflow","DevTools Debugging Workflow",[2061,2062,2063,2072,2078,2088,2094],"ol",{},[55,2064,2065,2068,2069,2071],{},[48,2066,2067],{},"See the clip shape."," In Chrome and Edge, select the element and click the shape icon next to ",[18,2070,33],{}," in the Styles pane to draw and edit the shape on the page. Firefox's Shapes editor does the same, including dragging polygon points.",[55,2073,2074,2077],{},[48,2075,2076],{},"Inspect interpolation."," The Animations panel in Chromium and Firefox lets you scrub a running animation. Pause at 50% and look for twisted polygons or jumping shapes, which indicate mismatched point counts or shape types.",[55,2079,2080,2083,2084,2087],{},[48,2081,2082],{},"Check registered properties."," In the Computed pane, a registered custom property shows a typed value such as ",[18,2085,2086],{},"180deg","; an unregistered one shows the raw token string. If a gradient animation snaps, check whether the property is registered.",[55,2089,2090,2093],{},[48,2091,2092],{},"Measure paint."," Enable Paint flashing in the Rendering drawer. Green flashes on every frame during a clip or mask animation confirm main-thread repaints — acceptable for short effects, a warning sign for loops.",[55,2095,2096,2099],{},[48,2097,2098],{},"Test hit areas."," Hover the edges of a clipped element; the cursor and hover styles should only respond within the visible shape.",[84,2101],{},[87,2103,2105],{"id":2104},"browser-compatibility","Browser Compatibility",[375,2107,2108,2124],{},[378,2109,2110],{},[381,2111,2112,2115,2118,2121],{},[384,2113,2114],{},"Feature",[384,2116,2117],{},"Chrome \u002F Edge",[384,2119,2120],{},"Firefox",[384,2122,2123],{},"Safari",[397,2125,2126,2140,2156,2172,2188,2203],{},[381,2127,2128,2133,2136,2138],{},[402,2129,2130,2132],{},[18,2131,33],{}," basic shapes + animation",[402,2134,2135],{},"Supported in all current versions",[402,2137,2135],{},[402,2139,2135],{},[381,2141,2142,2149,2152,2154],{},[402,2143,2144,2145,112,2147],{},"Unprefixed ",[18,2146,37],{},[18,2148,513],{},[402,2150,2151],{},"Supported in current versions",[402,2153,2151],{},[402,2155,2151],{},[381,2157,2158,2163,2166,2169],{},[402,2159,2160,2162],{},[18,2161,75],{}," (animatable gradients)",[402,2164,2165],{},"85+",[402,2167,2168],{},"128+",[402,2170,2171],{},"16.4+",[381,2173,2174,2179,2182,2185],{},[402,2175,2176,2178],{},[18,2177,857],{}," (spotlight example)",[402,2180,2181],{},"105+",[402,2183,2184],{},"121+",[402,2186,2187],{},"15.4+",[381,2189,2190,2194,2197,2200],{},[402,2191,2192],{},[18,2193,82],{},[402,2195,2196],{},"74+ \u002F 79+",[402,2198,2199],{},"63+",[402,2201,2202],{},"10.1+",[381,2204,2205,2210,2213,2216],{},[402,2206,2207,2209],{},[18,2208,1823],{}," (slider example)",[402,2211,2212],{},"93+",[402,2214,2215],{},"92+",[402,2217,2218],{},"26.2+",[14,2220,2221,2222,2225],{},"Older WebKit and Blink versions required ",[18,2223,2224],{},"-webkit-mask-*","; declaring the prefixed longhands before the unprefixed ones is still a reasonable safety net for sites that support older browser versions.",[84,2227],{},[87,2229,2231],{"id":2230},"common-pitfalls","Common Pitfalls",[375,2233,2234,2247],{},[378,2235,2236],{},[381,2237,2238,2241,2244],{},[384,2239,2240],{},"Pitfall",[384,2242,2243],{},"Cause",[384,2245,2246],{},"Resolution",[397,2248,2249,2260,2274,2285,2296],{},[381,2250,2251,2254,2257],{},[402,2252,2253],{},"Shape jumps instead of morphing",[402,2255,2256],{},"Different shape functions or point counts",[402,2258,2259],{},"Same function; pad polygons to equal counts",[381,2261,2262,2265,2268],{},[402,2263,2264],{},"Gradient mask or border does not animate",[402,2266,2267],{},"Unregistered custom property",[402,2269,2270,2271,2273],{},"Register it with ",[18,2272,75],{}," and a typed syntax",[381,2275,2276,2279,2282],{},[402,2277,2278],{},"Focus ring invisible",[402,2280,2281],{},"Outline is clipped with the element",[402,2283,2284],{},"Ring on an unclipped wrapper",[381,2286,2287,2290,2293],{},[402,2288,2289],{},"Content hidden for reduced-motion users",[402,2291,2292],{},"Animation removed but start clip kept",[402,2294,2295],{},"Set the end state explicitly",[381,2297,2298,2301,2304],{},[402,2299,2300],{},"Fade looks wrong in dark mode",[402,2302,2303],{},"Overlay gradient instead of a mask",[402,2305,2306,2307,2309],{},"Use ",[18,2308,37],{},", which has no colour",[84,2311],{},[87,2313,2315],{"id":2314},"faq","FAQ",[14,2317,2318,2326,2328,2329,2331],{},[48,2319,2320,2321,96,2323,2325],{},"What is the difference between ",[18,2322,33],{},[18,2324,37],{},"?",[18,2327,33],{}," cuts an element to a geometric shape with hard edges: every pixel is either fully visible or hidden. ",[18,2330,37],{}," uses an image's alpha or luminance to set partial transparency per pixel, so it can produce soft fades and textured edges. Clip-path shapes interpolate directly; mask gradients need a registered custom property to animate.",[14,2333,2334,2340,2341,2343],{},[48,2335,2336,2337,2339],{},"Do ",[18,2338,33],{}," and mask affect layout?","\nNo. Neither changes the element's box, so surrounding content never moves. Both do affect hit testing for ",[18,2342,33],{},", where clicks outside the clipped shape pass through, and both clip the element's outline and box-shadow, which matters for focus indicators.",[14,2345,2346,2352,2353,2355],{},[48,2347,2348,2349,2351],{},"Are ",[18,2350,33],{}," and mask animations GPU accelerated?","\nPartly and inconsistently. Some engines can composite certain mask and clip animations, but many ",[18,2354,33],{}," and gradient-mask animations repaint on the main thread each frame. Treat them as moderately expensive: fine for short, one-off effects, poor for long loops or many elements at once.",[14,2357,2358,2361,2362,2364],{},[48,2359,2360],{},"How do I keep a focus ring visible on a clipped element?","\nThe clip also clips the outline. Either clip an inner element and put the focus ring on an unclipped wrapper, or use an outline drawn inside the visible shape with a negative ",[18,2363,1861],{},". Never rely on the clipped shape itself to show focus.",[14,2366,2367,2370],{},[48,2368,2369],{},"What should reduced-motion users see instead of a reveal?","\nThe final state, immediately. Remove the animation and set the clip or mask to its end value, or remove it entirely. Simply dropping the animation can leave the element stuck at its starting clip, which is often fully hidden.",[87,2372,2374],{"id":2373},"related","Related",[52,2376,2377,2382,2387,2392,2397,2404],{},[55,2378,2379,2381],{},[40,2380,246],{"href":245}," — wipes, irises and diagonal reveals.",[55,2383,2384,2386],{},[40,2385,251],{"href":250}," — point-matched icon morphs.",[55,2388,2389,2391],{},[40,2390,256],{"href":255}," — soft boundaries on any background.",[55,2393,2394,2396],{},[40,2395,261],{"href":260}," — rotating rings with a registered angle.",[55,2398,2399,2403],{},[40,2400,2402],{"href":2401},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002F","Performance & GPU Acceleration"," — what these effects cost to render.",[55,2405,2406,2410],{},[40,2407,2409],{"href":2408},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media\u002F","Aspect Ratio for Responsive Media"," — reserving stable boxes for clipped media.",[1414,2412,2413],{},"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 .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html pre.shiki code .sKwhi, html code.shiki .sKwhi{--shiki-default:#622CBC;--shiki-dark:#DBB7FF}",{"title":625,"searchDepth":642,"depth":642,"links":2415},[2416,2419,2420,2427,2428,2429,2430,2431,2432,2433,2434,2435],{"id":89,"depth":642,"text":90,"children":2417},[2418],{"id":266,"depth":657,"text":267},{"id":372,"depth":642,"text":373},{"id":610,"depth":642,"text":611,"children":2421},[2422,2423,2424,2425,2426],{"id":617,"depth":657,"text":618},{"id":786,"depth":657,"text":787},{"id":861,"depth":657,"text":862},{"id":1092,"depth":657,"text":1093},{"id":1151,"depth":657,"text":1152},{"id":1195,"depth":642,"text":1196},{"id":1884,"depth":642,"text":1885},{"id":1922,"depth":642,"text":1923},{"id":2004,"depth":642,"text":2005},{"id":2058,"depth":642,"text":2059},{"id":2104,"depth":642,"text":2105},{"id":2230,"depth":642,"text":2231},{"id":2314,"depth":642,"text":2315},{"id":2373,"depth":642,"text":2374},"Animate what is visible rather than what moves: clip-path shapes, mask gradients, registered properties for animated gradients, costs and accessible fallbacks.","md",{"pageTitle":2439,"datePublished":2440,"dateModified":2440,"faq":2441},"Clip-Path and Mask Animations in CSS","2026-09-18",[2442,2445,2448,2451,2453],{"q":2443,"a":2444},"What is the difference between clip-path and mask-image?","clip-path cuts an element to a geometric shape with hard edges: every pixel is either fully visible or hidden. mask-image uses an image's alpha or luminance to set partial transparency per pixel, so it can produce soft fades and textured edges. Clip-path shapes interpolate directly; mask gradients need a registered custom property to animate.",{"q":2446,"a":2447},"Do clip-path and mask affect layout?","No. Neither changes the element's box, so surrounding content never moves. Both do affect hit testing for clip-path, where clicks outside the clipped shape pass through, and both clip the element's outline and box-shadow, which matters for focus indicators.",{"q":2449,"a":2450},"Are clip-path and mask animations GPU accelerated?","Partly and inconsistently. Some engines can composite certain mask and clip animations, but many clip-path and gradient-mask animations repaint on the main thread each frame. Treat them as moderately expensive: fine for short, one-off effects, poor for long loops or many elements at once.",{"q":2360,"a":2452},"The clip also clips the outline. Either clip an inner element and put the focus ring on an unclipped wrapper, or use an outline drawn inside the visible shape with a negative outline-offset. Never rely on the clipped shape itself to show focus.",{"q":2369,"a":2454},"The final state, immediately. Remove the animation and set the clip or mask to its end value, or remove it entirely. Simply dropping the animation can leave the element stuck at its starting clip, which is often fully hidden.","\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations",{"title":5,"description":2436},"css-only-micro-interactions-animations\u002Fclip-path-and-mask-animations\u002Findex","K01L1Aqik35Wd9GAg4nHfrmVek_JeGFYxvBH5nLFVfY",[2460,2463,2466,2469,2472,2475,2478,2481,2484,2487,2490,2493,2496,2497,2500,2503,2506,2509,2512,2515,2518,2521,2524,2527,2530,2533,2536,2539,2542,2545,2548,2551,2554,2557,2560,2563,2566,2569,2572,2575,2578,2581,2584,2587,2590,2593,2596,2599,2602,2605,2608,2611,2614,2617,2620,2623,2626,2629,2632,2635,2638,2641,2644,2647,2650,2653,2656,2659,2662,2665,2668,2671,2674,2677,2680,2683,2686,2689,2692,2695,2698,2701,2704,2707,2710,2713,2716,2719,2722,2725,2728,2731,2734,2737,2740,2743,2746,2749,2752,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,2896,2899,2902,2905,2908,2911,2914,2917,2920,2923,2926,2929,2932,2935,2938,2941,2944,2947,2950,2953,2956,2959,2962,2965,2968,2971,2974,2977,2980,2983,2986,2989,2992,2995,2998,3001,3004,3007,3010,3013,3016],{"path":2461,"title":2462},"\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":2464,"title":2465},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds","Flashing Content and Seizure Thresholds",{"path":2467,"title":2468},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fforced-colors-mode-and-animations","Forced Colors Mode and Animations",{"path":2470,"title":2471},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":2473,"title":2474},"\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":2476,"title":2477},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":2479,"title":2480},"\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":2482,"title":2483},"\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":2485,"title":2486},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":2488,"title":2489},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":2491,"title":2492},"\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":2494,"title":2495},"\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":2455,"title":5},{"path":2498,"title":2499},"\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":2501,"title":2502},"\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":2504,"title":2505},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fanimating-gradients","Animating CSS Gradients: Smooth Colour Motion Without Jumps",{"path":2507,"title":2508},"\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":2510,"title":2511},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions","Color & Theme Transitions: Colour as Part of the Motion System",{"path":2513,"title":2514},"\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":2516,"title":2517},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fsmooth-theme-switching-transitions","Smooth Theme Switching: Crossfades, Circular Reveals and No Flash",{"path":2519,"title":2520},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":2522,"title":2523},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":2525,"title":2526},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Flayout-change-animations-at-container-breakpoints","Animating Changes at Container Breakpoints",{"path":2528,"title":2529},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries","Motion Driven by Container Style Queries",{"path":2531,"title":2532},"\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":2534,"title":2535},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":2537,"title":2538},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript","Controlling CSS Animations From JavaScript",{"path":2540,"title":2541},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":2543,"title":2544},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui","Interruptible UI: CSS Transitions vs WAAPI",{"path":2546,"title":2547},"\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":2549,"title":2550},"\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":2552,"title":2553},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values","Custom Property Fallbacks and Invalid Values",{"path":2555,"title":2556},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":2558,"title":2559},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":2561,"title":2562},"\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":2564,"title":2565},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components","Scoping Custom Properties to Components",{"path":2567,"title":2568},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":2570,"title":2571},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":2573,"title":2574},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions","Interrupted and Reversing Transitions: What Happens Mid-Flight",{"path":2576,"title":2577},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":2579,"title":2580},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-delay-choreography","Choreographing Motion With transition-delay",{"path":2582,"title":2583},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties","The transition Shorthand and Multiple Properties",{"path":2585,"title":2586},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":2588,"title":2589},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fanimating-dialog-open-and-close","Animating \u003Cdialog> Open and Close: Both Directions, No Library",{"path":2591,"title":2592},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fbackdrop-animations","Animating ::backdrop: Fades and Blurs Behind Dialogs and Popovers",{"path":2594,"title":2595},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations","Dialog & Popover Animations: Motion for the Top Layer",{"path":2597,"title":2598},"\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":2600,"title":2601},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fpopover-entry-and-exit-transitions","Popover Menus That Animate From Their Anchor",{"path":2603,"title":2604},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations","Choosing Animation Durations: How Long Motion Should Last",{"path":2606,"title":2607},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fcubic-bezier-overshoot-and-anticipation","Overshoot and Anticipation With cubic-bezier(): Motion With Character",{"path":2609,"title":2610},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fentry-vs-exit-easing","Entry vs Exit Easing: Different Curves for Arriving and Leaving",{"path":2612,"title":2613},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design","Easing & Motion Design: Making CSS Motion Feel Intentional",{"path":2615,"title":2616},"\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":2618,"title":2619},"\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":2621,"title":2622},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":2624,"title":2625},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fbutton-press-and-active-states","Button Press and  States",{"path":2627,"title":2628},"\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":2630,"title":2631},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":2633,"title":2634},"\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":2636,"title":2637},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":2639,"title":2640},"\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":2642,"title":2643},"\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":2645,"title":2646},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":2648,"title":2649},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-composition-and-stacking","Stacking Animations With animation-composition",{"path":2651,"title":2652},"\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":2654,"title":2655},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":2657,"title":2658},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":2660,"title":2661},"\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":2663,"title":2664},"\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":2666,"title":2667},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":2669,"title":2670},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fmulti-step-keyframes-and-per-keyframe-easing","Multi-Step Keyframes and Per-Keyframe Easing",{"path":2672,"title":2673},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":2675,"title":2676},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fanimating-box-shadow-and-filters-cheaply","Animating box-shadow and Filters Cheaply",{"path":2678,"title":2679},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcontain-property-for-animation-performance","The contain Property for Animation Performance",{"path":2681,"title":2682},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcss-triggers-layout-paint-composite","Layout, Paint and Composite: What Triggers What",{"path":2684,"title":2685},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":2687,"title":2688},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":2690,"title":2691},"\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":2693,"title":2694},"\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":2696,"title":2697},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":2699,"title":2700},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":2702,"title":2703},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-parallax-effects","Scroll-Driven Parallax Effects in CSS",{"path":2705,"title":2706},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":2708,"title":2709},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":2711,"title":2712},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Ftimeline-scope-for-cross-element-animations","timeline-scope for Cross-Element Animations",{"path":2714,"title":2715},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fview-timeline-and-animation-range","View Timelines and animation-range",{"path":2717,"title":2718},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fcross-document-view-transitions","Cross-Document View Transitions",{"path":2720,"title":2721},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":2723,"title":2724},"\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":2726,"title":2727},"\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":2729,"title":2730},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-types-and-classes","View Transition Types and Classes",{"path":2732,"title":2733},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-for-list-reordering","View Transitions for List Reordering",{"path":2735,"title":2736},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":2738,"title":2739},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":2741,"title":2742},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":2744,"title":2745},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":2747,"title":2748},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-size-for-matching-widths","anchor-size(): Overlays That Match Their Trigger's Size",{"path":2750,"title":2751},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":2753,"title":2754},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":2756,"title":2757},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-light-dismiss-and-stacking","Popover Light Dismiss, Nesting and Stacking",{"path":2759,"title":2760},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fposition-area-grid-explained","position-area: The Anchor Placement Grid",{"path":2762,"title":2763},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fcontainer-query-polyfill-tradeoffs","Container Query Polyfills: What They Cost and When to Skip Them",{"path":2765,"title":2766},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":2768,"title":2769},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":2771,"title":2772},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":2774,"title":2775},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fintrinsic-layout-fallbacks-without-queries","Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query",{"path":2777,"title":2778},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ftesting-fallbacks-without-old-browsers","Testing CSS Fallbacks Without an Old Browser",{"path":2780,"title":2781},"\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":2783,"title":2784},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-range-and-logic-operators","Container Query Range Syntax and Logic Operators",{"path":2786,"title":2787},"\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":2789,"title":2790},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":2792,"title":2793},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":2795,"title":2796},"\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":2798,"title":2799},"\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":2801,"title":2802},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":2804,"title":2805},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":2807,"title":2808},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":2810,"title":2811},"\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":2813,"title":2814},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-auto-flow-dense-packing","grid-auto-flow: dense for Packed Layouts",{"path":2816,"title":2817},"\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":2819,"title":2820},"\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":2822,"title":2823},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":2825,"title":2826},"\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":2828,"title":2829},"\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":2831,"title":2832},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":2834,"title":2835},"\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":2837,"title":2838},"\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":2840,"title":2841},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-grow-and-flex-shrink-explained","flex-grow and flex-shrink Explained",{"path":2843,"title":2844},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-wrap-intrinsic-responsive-rows","Breakpoint-Free Responsive Rows With flex-wrap and flex-basis",{"path":2846,"title":2847},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflexbox-gap-and-spacing","Flexbox gap vs Margins: Spacing Items Without Edge Hacks",{"path":2849,"title":2850},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns","Flexbox Layout Patterns: One-Dimensional Layout for Real Components",{"path":2852,"title":2853},"\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":2855,"title":2856},"\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":2858,"title":2859},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fdebugging-clamp-values","Debugging clamp(): Values That Are Ignored, Stuck or Never Fluid",{"path":2861,"title":2862},"\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":2864,"title":2865},"\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":2867,"title":2868},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":2870,"title":2871},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":2873,"title":2874},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":2876,"title":2877},"\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":2879,"title":2880},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":2882,"title":2883},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":2885,"title":2886},"\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":2888,"title":2889},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":2891,"title":2892},"\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":2894,"title":2895},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":2897,"title":2898},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fobject-fit-and-object-position","object-fit and object-position: Images That Fit Any Box",{"path":2900,"title":2901},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":2903,"title":2904},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":2906,"title":2907},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":2909,"title":2910},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcss-scope-for-component-styles","@scope for Component Styles: Short Selectors That Cannot Leak",{"path":2912,"title":2913},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":2915,"title":2916},"\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":2918,"title":2919},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fwriting-a-minimal-modern-reset","Writing a Minimal Modern CSS Reset: Every Line Justified",{"path":2921,"title":2922},"\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":2924,"title":2925},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fempty-and-loading-states-with-has","Empty and Loading States With ()",{"path":2927,"title":2928},"\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":2930,"title":2931},"\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":2933,"title":2934},"\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":2936,"title":2937},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has","Parent-Aware Layouts With :has(): Letting Containers React to Their Contents",{"path":2939,"title":2940},"\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":2942,"title":2943},"\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":2945,"title":2946},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":2948,"title":2949},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":2951,"title":2952},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":2954,"title":2955},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":2957,"title":2958},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-hero-sections-with-container-queries","Responsive Hero Sections With Container Queries",{"path":2960,"title":2961},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":2963,"title":2964},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-pricing-tables","Responsive Pricing Tables: Aligned Features, a Clear Recommendation, Any Width",{"path":2966,"title":2967},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Ftabs-that-become-accordions","Tabs That Become an Accordion: One Component, Two Layouts",{"path":2969,"title":2970},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap","A CSS-Only Carousel With Scroll Snap",{"path":2972,"title":2973},"\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":2975,"title":2976},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts","Scroll Snap & Overflow Layouts: Designing Components That Scroll on Purpose",{"path":2978,"title":2979},"\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":2981,"title":2982},"\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":2984,"title":2985},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcombining-size-and-style-queries","Combining Size and Style Container Queries",{"path":2987,"title":2988},"\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":2990,"title":2991},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":2993,"title":2994},"\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":2996,"title":2997},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-component-variants","Component Variants With Style Queries: One Token, Many Looks",{"path":2999,"title":3000},"\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":3002,"title":3003},"\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":3005,"title":3006},"\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":3008,"title":3009},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout","Viewport Units & Mobile Layout: Designing for the Screen You Actually Get",{"path":3011,"title":3012},"\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":3014,"title":3015},"\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":3017,"title":3018},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fvirtual-keyboard-and-interactive-widget","Layouts That Survive the Virtual Keyboard",{"title":3020,"caption":3021,"height":3022,"html":3023,"css":3024},"Before and after comparison clipped with inset()","This frame has no script, so the reveal is fixed at 50%; on a real page one line of script copies the range value into --pos.",280,"\n\u003Cfigure class=\"compare\" style=\"--pos: 50%\">\n  \u003Cdiv class=\"compare__before\" role=\"img\" aria-label=\"Before\">\u003C\u002Fdiv>\n  \u003Cdiv class=\"compare__after\" role=\"img\" aria-label=\"After\">\u003C\u002Fdiv>\n  \u003Cspan class=\"compare__label compare__label--before\">Before\u003C\u002Fspan>\n  \u003Cspan class=\"compare__label compare__label--after\">After\u003C\u002Fspan>\n\u003C\u002Ffigure>","\nbody { display: block; }\n.compare { position: relative; display: grid; aspect-ratio: 16 \u002F 9; max-height: 230px; margin: 0 auto; border-radius: 12px; overflow: hidden; }\n.compare__before, .compare__after, .compare__label { grid-area: 1 \u002F 1; }\n.compare__before { background: linear-gradient(135deg, #78716c, #44403c); }\n.compare__after { background: linear-gradient(135deg, #fde68a, #f59e0b); clip-path: inset(0 calc(100% - var(--pos)) 0 0); }\n.compare__label { align-self: start; margin: 0.5rem; padding: 0.1rem 0.5rem; border-radius: 4px; background: rgb(15 23 42 \u002F 0.8); color: #f8fafc; font-size: 0.8rem; }\n.compare__label--before { justify-self: end; }\n.compare__label--after { justify-self: start; }",1789717745536]