[{"data":1,"prerenderedAt":1716},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds":3,"content-all-pages":1151,"live-demo:safe-attention-pulse":1710},{"id":4,"title":5,"body":6,"description":1134,"extension":1135,"meta":1136,"navigation":388,"path":1147,"seo":1148,"stem":1149,"__hash__":1150},"content\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds\u002Findex.md","Flashing Content and Seizure Thresholds",{"type":7,"value":8,"toc":1122},"minimark",[9,13,33,38,58,65,141,149,153,160,182,193,197,200,204,897,907,911,914,975,978,982,985,1016,1020,1023,1027,1039,1043,1061,1065,1071,1077,1083,1089,1093,1119],[10,11,5],"h1",{"id":12},"flashing-content-and-seizure-thresholds",[14,15,16,17,21,22,27,28,32],"p",{},"Most animation accessibility advice is about comfort: motion that distracts, dizzies or annoys. Flashing is different. Content that flashes at certain frequencies and intensities can trigger seizures in people with photosensitive epilepsy, and the harm is immediate and severe. That is why WCAG treats it as a Level A requirement — the most basic tier — and why it applies whether or not a user has expressed any preference. CSS makes flashing trivially easy to create by accident: an ",[18,19,20],"code",{},"infinite alternate"," animation on a background colour with a short duration, a blinking error border, a \"strobe\" effect on a sale banner. This page explains what counts as a flash, the thresholds, and patterns that draw attention without approaching them. It belongs to ",[23,24,26],"a",{"href":25},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002F","Accessibility in CSS Animations"," in the ",[23,29,31],{"href":30},"\u002Fcss-only-micro-interactions-animations\u002F","CSS-Only Micro-Interactions & Animations"," guide.",[34,35,37],"h2",{"id":36},"what-wcag-requires","What WCAG requires",[14,39,40,41,45,46,49,50,53,54,57],{},"Success criterion 2.3.1, ",[42,43,44],"em",{},"Three Flashes or Below Threshold",", says web pages must not contain anything that flashes more than three times in any one-second period, unless the flash is below the ",[42,47,48],{},"general flash"," and ",[42,51,52],{},"red flash"," thresholds. The AAA criterion 2.3.2, ",[42,55,56],{},"Three Flashes",", removes the threshold exception: nothing may flash more than three times per second at all.",[14,59,60,61,64],{},"A ",[42,62,63],{},"flash"," is a pair of opposing changes in relative luminance — bright to dark and back — where the darker state is dark enough and the change is large enough. Specifically, the general flash threshold is crossed when the change is 10% or more of maximum relative luminance, the darker image is below 0.80 relative luminance, and the flashing area together is larger than roughly a quarter of a 10-degree visual field (the guidelines approximate this as 341 by 256 pixels at typical viewing distances on a 1024 by 768 screen). The red flash threshold covers transitions to or from saturated red, which is especially provocative.",[66,67,73,74,73,78,73,82,73,90,73,99,73,102,73,109,73,112,73,119,73,123,73,129,73,133,73,138],"svg",{"viewBox":68,"role":69,"ariaLabel":70,"xmlns":71,"style":72},"0 0 720 300","img","Luminance over one second for two animations: one with two flashes, which passes, and one with six flashes, which fails the three-per-second rule","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[75,76,77],"title",{},"Counting flashes in one second",[79,80,81],"desc",{},"Two luminance traces across a one-second window. The top trace rises and falls twice, a slow pulse that stays within three flashes per second and passes. The bottom trace alternates six times in the same window, like an 83 millisecond alternate animation, and fails because it exceeds three flashes per second.",[83,84,89],"text",{"textAnchor":85,"x":86,"y":87,"style":88},"middle","360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","Any one-second window, at most three flashes",[91,92],"line",{"x1":93,"y1":94,"x2":95,"y2":94,"stroke":96,"strokeWidth":97,"opacity":98},"100","130","660","currentColor","1","0.4",[91,100],{"x1":93,"y1":101,"x2":95,"y2":101,"stroke":96,"strokeWidth":97,"opacity":98},"250",[103,104],"path",{"d":105,"fill":106,"stroke":107,"strokeWidth":108},"M100 130 C170 130 170 70 240 70 C310 70 310 130 380 130 C450 130 450 70 520 70 C590 70 590 130 660 130","none","#7aa2ff","3",[103,110],{"d":111,"fill":106,"stroke":96,"strokeWidth":108},"M100 250 V190 H147 V250 H193 V190 H240 V250 H287 V190 H333 V250 H380 V190 H427 V250 H473 V190 H520 V250 H567 V190 H613 V250 H660",[83,113,118],{"textAnchor":114,"x":115,"y":116,"style":117},"end","90","104","text-anchor:end;fill:currentColor;font:600 12px sans-serif","pass",[83,120,122],{"textAnchor":114,"x":115,"y":121,"style":117},"224","fail",[83,124,128],{"textAnchor":85,"x":125,"y":126,"style":127},"380","58","text-anchor:middle;fill:currentColor;font:12px sans-serif","slow pulse, 2 cycles",[83,130,132],{"textAnchor":85,"x":125,"y":131,"style":127},"178","hard alternation, 6 flashes",[83,134,137],{"textAnchor":85,"x":93,"y":135,"style":136},"274","text-anchor:middle;fill:currentColor;font:11px sans-serif","0 s",[83,139,140],{"textAnchor":85,"x":95,"y":135,"style":136},"1 s",[14,142,143,144,148],{},"Measuring exact luminance and area by hand is impractical, which is why teams usually adopt a simpler rule that stays well clear: ",[145,146,147],"strong",{},"no more than three luminance reversals per second, ever, and avoid large, high-contrast alternation entirely."," Tools such as the Photosensitive Epilepsy Analysis Tool (PEAT) analyse recorded video when a precise assessment is required.",[34,150,152],{"id":151},"translating-the-rule-into-css-durations","Translating the rule into CSS durations",[14,154,155,156,159],{},"For an ",[18,157,158],{},"alternate"," animation, each iteration is one change. A full flash is two changes — bright to dark and back — so an animation alternating every 166 milliseconds produces three flashes per second. That makes the arithmetic:",[161,162,163,170,176],"ul",{},[164,165,166,169],"li",{},[18,167,168],{},"animation: blink 166ms steps(1) infinite alternate"," — right at the limit. Never do this with high-contrast content.",[164,171,172,175],{},[18,173,174],{},"animation: blink 500ms ease-in-out infinite alternate"," — one flash per second, with soft transitions rather than hard cuts.",[164,177,178,181],{},[18,179,180],{},"animation: blink 1s ease-in-out infinite alternate"," — one flash every two seconds.",[14,183,184,185,188,189,192],{},"Easing matters as much as frequency. A ",[18,186,187],{},"steps(1)"," or ",[18,190,191],{},"step-end"," timing produces instant cuts between states, the most intense kind of flash. A smooth ease-in-out spreads the luminance change over the whole duration, which is gentler even at the same rate.",[34,194,196],{"id":195},"the-complete-implementation","The complete implementation",[14,198,199],{},"An attention cue that stays far below every threshold: a slow, low-contrast pulse on a notification badge, limited to a few iterations, plus a static alternative. Compare it with the demo's \"don't\" example, which is rendered safely here as a static description rather than an actual strobe.",[201,202],"live-demo",{"name":203},"safe-attention-pulse",[205,206,211],"pre",{"className":207,"code":208,"language":209,"meta":210,"style":210},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003C!doctype html>\n\u003Chtml lang=\"en\">\n\u003Chead>\n\u003Cmeta charset=\"utf-8\">\n\u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\u003Ctitle>Safe attention pulse\u003C\u002Ftitle>\n\u003Cstyle>\n  body { font: 15px\u002F1.5 system-ui, sans-serif; margin: 2rem; }\n\n  .badge {\n    display: inline-grid;\n    place-items: center;\n    min-inline-size: 1.5rem;\n    block-size: 1.5rem;\n    padding-inline: 0.4rem;\n    border-radius: 999px;\n    background: #2563eb;\n    color: #fff;\n    font-size: 0.8rem;\n    font-weight: 700;\n  }\n\n  .badge--new {\n    \u002F* 1.2s per half-cycle: well under one flash per second.\n       Scale and a soft ring, not a luminance flip. *\u002F\n    animation: attention 1.2s ease-in-out 4 alternate both;  \u002F* even count: ends at rest *\u002F\n  }\n\n  @keyframes attention {\n    from { box-shadow: 0 0 0 0 rgb(37 99 235 \u002F 0.45); scale: 1; }\n    to   { box-shadow: 0 0 0 6px rgb(37 99 235 \u002F 0); scale: 1.08; }\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    .badge--new {\n      animation: none;\n      outline: 2px solid #1d4ed8;   \u002F* a static cue *\u002F\n      outline-offset: 2px;\n    }\n  }\n\u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Cp>Inbox \u003Cspan class=\"badge badge--new\">3\u003C\u002Fspan>\u003C\u002Fp>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html","",[18,212,213,232,252,262,280,305,319,329,383,390,399,413,426,440,454,468,483,496,509,524,537,543,548,556,563,569,602,607,612,624,680,729,734,739,748,756,768,792,806,812,817,827,836,846,879,888],{"__ignoreMap":210},[214,215,217,221,225,229],"span",{"class":91,"line":216},1,[214,218,220],{"class":219},"suds8","\u003C!",[214,222,224],{"class":223},"sne4z","doctype",[214,226,228],{"class":227},"s-5SL"," html",[214,230,231],{"class":219},">\n",[214,233,235,238,240,243,246,250],{"class":91,"line":234},2,[214,236,237],{"class":219},"\u003C",[214,239,209],{"class":223},[214,241,242],{"class":227}," lang",[214,244,245],{"class":219},"=",[214,247,249],{"class":248},"sT6z2","\"en\"",[214,251,231],{"class":219},[214,253,255,257,260],{"class":91,"line":254},3,[214,256,237],{"class":219},[214,258,259],{"class":223},"head",[214,261,231],{"class":219},[214,263,265,267,270,273,275,278],{"class":91,"line":264},4,[214,266,237],{"class":219},[214,268,269],{"class":223},"meta",[214,271,272],{"class":227}," charset",[214,274,245],{"class":219},[214,276,277],{"class":248},"\"utf-8\"",[214,279,231],{"class":219},[214,281,283,285,287,290,292,295,298,300,303],{"class":91,"line":282},5,[214,284,237],{"class":219},[214,286,269],{"class":223},[214,288,289],{"class":227}," name",[214,291,245],{"class":219},[214,293,294],{"class":248},"\"viewport\"",[214,296,297],{"class":227}," content",[214,299,245],{"class":219},[214,301,302],{"class":248},"\"width=device-width, initial-scale=1\"",[214,304,231],{"class":219},[214,306,308,310,312,315,317],{"class":91,"line":307},6,[214,309,237],{"class":219},[214,311,75],{"class":223},[214,313,314],{"class":219},">Safe attention pulse\u003C\u002F",[214,316,75],{"class":223},[214,318,231],{"class":219},[214,320,322,324,327],{"class":91,"line":321},7,[214,323,237],{"class":219},[214,325,326],{"class":223},"style",[214,328,231],{"class":219},[214,330,332,335,338,341,344,347,351,354,357,360,363,366,369,372,374,377,380],{"class":91,"line":331},8,[214,333,334],{"class":223},"  body",[214,336,337],{"class":219}," { ",[214,339,340],{"class":227},"font",[214,342,343],{"class":219},": ",[214,345,346],{"class":227},"15",[214,348,350],{"class":349},"sHUrx","px",[214,352,353],{"class":219},"\u002F",[214,355,356],{"class":227},"1.5",[214,358,359],{"class":227}," system-ui",[214,361,362],{"class":219},", ",[214,364,365],{"class":227},"sans-serif",[214,367,368],{"class":219},"; ",[214,370,371],{"class":227},"margin",[214,373,343],{"class":219},[214,375,376],{"class":227},"2",[214,378,379],{"class":349},"rem",[214,381,382],{"class":219},"; }\n",[214,384,386],{"class":91,"line":385},9,[214,387,389],{"emptyLinePlaceholder":388},true,"\n",[214,391,393,396],{"class":91,"line":392},10,[214,394,395],{"class":227},"  .badge",[214,397,398],{"class":219}," {\n",[214,400,402,405,407,410],{"class":91,"line":401},11,[214,403,404],{"class":227},"    display",[214,406,343],{"class":219},[214,408,409],{"class":227},"inline-grid",[214,411,412],{"class":219},";\n",[214,414,416,419,421,424],{"class":91,"line":415},12,[214,417,418],{"class":227},"    place-items",[214,420,343],{"class":219},[214,422,423],{"class":227},"center",[214,425,412],{"class":219},[214,427,429,432,434,436,438],{"class":91,"line":428},13,[214,430,431],{"class":227},"    min-inline-size",[214,433,343],{"class":219},[214,435,356],{"class":227},[214,437,379],{"class":349},[214,439,412],{"class":219},[214,441,443,446,448,450,452],{"class":91,"line":442},14,[214,444,445],{"class":227},"    block-size",[214,447,343],{"class":219},[214,449,356],{"class":227},[214,451,379],{"class":349},[214,453,412],{"class":219},[214,455,457,460,462,464,466],{"class":91,"line":456},15,[214,458,459],{"class":227},"    padding-inline",[214,461,343],{"class":219},[214,463,98],{"class":227},[214,465,379],{"class":349},[214,467,412],{"class":219},[214,469,471,474,476,479,481],{"class":91,"line":470},16,[214,472,473],{"class":227},"    border-radius",[214,475,343],{"class":219},[214,477,478],{"class":227},"999",[214,480,350],{"class":349},[214,482,412],{"class":219},[214,484,486,489,491,494],{"class":91,"line":485},17,[214,487,488],{"class":227},"    background",[214,490,343],{"class":219},[214,492,493],{"class":227},"#2563eb",[214,495,412],{"class":219},[214,497,499,502,504,507],{"class":91,"line":498},18,[214,500,501],{"class":227},"    color",[214,503,343],{"class":219},[214,505,506],{"class":227},"#fff",[214,508,412],{"class":219},[214,510,512,515,517,520,522],{"class":91,"line":511},19,[214,513,514],{"class":227},"    font-size",[214,516,343],{"class":219},[214,518,519],{"class":227},"0.8",[214,521,379],{"class":349},[214,523,412],{"class":219},[214,525,527,530,532,535],{"class":91,"line":526},20,[214,528,529],{"class":227},"    font-weight",[214,531,343],{"class":219},[214,533,534],{"class":227},"700",[214,536,412],{"class":219},[214,538,540],{"class":91,"line":539},21,[214,541,542],{"class":219},"  }\n",[214,544,546],{"class":91,"line":545},22,[214,547,389],{"emptyLinePlaceholder":388},[214,549,551,554],{"class":91,"line":550},23,[214,552,553],{"class":227},"  .badge--new",[214,555,398],{"class":219},[214,557,559],{"class":91,"line":558},24,[214,560,562],{"class":561},"sLBg1","    \u002F* 1.2s per half-cycle: well under one flash per second.\n",[214,564,566],{"class":91,"line":565},25,[214,567,568],{"class":561},"       Scale and a soft ring, not a luminance flip. *\u002F\n",[214,570,572,575,578,581,584,587,590,593,596,599],{"class":91,"line":571},26,[214,573,574],{"class":227},"    animation",[214,576,577],{"class":219},": attention ",[214,579,580],{"class":227},"1.2",[214,582,583],{"class":349},"s",[214,585,586],{"class":227}," ease-in-out",[214,588,589],{"class":227}," 4",[214,591,592],{"class":227}," alternate",[214,594,595],{"class":227}," both",[214,597,598],{"class":219},";  ",[214,600,601],{"class":561},"\u002F* even count: ends at rest *\u002F\n",[214,603,605],{"class":91,"line":604},27,[214,606,542],{"class":219},[214,608,610],{"class":91,"line":609},28,[214,611,389],{"emptyLinePlaceholder":388},[214,613,615,618,622],{"class":91,"line":614},29,[214,616,617],{"class":349},"  @keyframes",[214,619,621],{"class":620},"soyes"," attention",[214,623,398],{"class":219},[214,625,627,630,632,635,637,640,643,645,647,650,653,656,659,662,665,668,671,674,676,678],{"class":91,"line":626},30,[214,628,629],{"class":227},"    from",[214,631,337],{"class":219},[214,633,634],{"class":227},"box-shadow",[214,636,343],{"class":219},[214,638,639],{"class":227},"0",[214,641,642],{"class":227}," 0",[214,644,642],{"class":227},[214,646,642],{"class":227},[214,648,649],{"class":227}," rgb",[214,651,652],{"class":219},"(",[214,654,655],{"class":227},"37",[214,657,658],{"class":227}," 99",[214,660,661],{"class":227}," 235",[214,663,664],{"class":219}," \u002F ",[214,666,667],{"class":227},"0.45",[214,669,670],{"class":219},"); ",[214,672,673],{"class":227},"scale",[214,675,343],{"class":219},[214,677,97],{"class":227},[214,679,382],{"class":219},[214,681,683,686,689,691,693,695,697,699,702,704,706,708,710,712,714,716,718,720,722,724,727],{"class":91,"line":682},31,[214,684,685],{"class":227},"    to",[214,687,688],{"class":219},"   { ",[214,690,634],{"class":227},[214,692,343],{"class":219},[214,694,639],{"class":227},[214,696,642],{"class":227},[214,698,642],{"class":227},[214,700,701],{"class":227}," 6",[214,703,350],{"class":349},[214,705,649],{"class":227},[214,707,652],{"class":219},[214,709,655],{"class":227},[214,711,658],{"class":227},[214,713,661],{"class":227},[214,715,664],{"class":219},[214,717,639],{"class":227},[214,719,670],{"class":219},[214,721,673],{"class":227},[214,723,343],{"class":219},[214,725,726],{"class":227},"1.08",[214,728,382],{"class":219},[214,730,732],{"class":91,"line":731},32,[214,733,542],{"class":219},[214,735,737],{"class":91,"line":736},33,[214,738,389],{"emptyLinePlaceholder":388},[214,740,742,745],{"class":91,"line":741},34,[214,743,744],{"class":349},"  @media",[214,746,747],{"class":219}," (prefers-reduced-motion: reduce) {\n",[214,749,751,754],{"class":91,"line":750},35,[214,752,753],{"class":227},"    .badge--new",[214,755,398],{"class":219},[214,757,759,762,764,766],{"class":91,"line":758},36,[214,760,761],{"class":227},"      animation",[214,763,343],{"class":219},[214,765,106],{"class":227},[214,767,412],{"class":219},[214,769,771,774,776,778,780,783,786,789],{"class":91,"line":770},37,[214,772,773],{"class":227},"      outline",[214,775,343],{"class":219},[214,777,376],{"class":227},[214,779,350],{"class":349},[214,781,782],{"class":227}," solid",[214,784,785],{"class":227}," #1d4ed8",[214,787,788],{"class":219},";   ",[214,790,791],{"class":561},"\u002F* a static cue *\u002F\n",[214,793,795,798,800,802,804],{"class":91,"line":794},38,[214,796,797],{"class":227},"      outline-offset",[214,799,343],{"class":219},[214,801,376],{"class":227},[214,803,350],{"class":349},[214,805,412],{"class":219},[214,807,809],{"class":91,"line":808},39,[214,810,811],{"class":219},"    }\n",[214,813,815],{"class":91,"line":814},40,[214,816,542],{"class":219},[214,818,820,823,825],{"class":91,"line":819},41,[214,821,822],{"class":219},"\u003C\u002F",[214,824,326],{"class":223},[214,826,231],{"class":219},[214,828,830,832,834],{"class":91,"line":829},42,[214,831,822],{"class":219},[214,833,259],{"class":223},[214,835,231],{"class":219},[214,837,839,841,844],{"class":91,"line":838},43,[214,840,237],{"class":219},[214,842,843],{"class":223},"body",[214,845,231],{"class":219},[214,847,849,852,854,857,859,862,864,867,870,872,875,877],{"class":91,"line":848},44,[214,850,851],{"class":219},"  \u003C",[214,853,14],{"class":223},[214,855,856],{"class":219},">Inbox \u003C",[214,858,214],{"class":223},[214,860,861],{"class":227}," class",[214,863,245],{"class":219},[214,865,866],{"class":248},"\"badge badge--new\"",[214,868,869],{"class":219},">3\u003C\u002F",[214,871,214],{"class":223},[214,873,874],{"class":219},">\u003C\u002F",[214,876,14],{"class":223},[214,878,231],{"class":219},[214,880,882,884,886],{"class":91,"line":881},45,[214,883,822],{"class":219},[214,885,843],{"class":223},[214,887,231],{"class":219},[214,889,891,893,895],{"class":91,"line":890},46,[214,892,822],{"class":219},[214,894,209],{"class":223},[214,896,231],{"class":219},[14,898,899,900,902,903,906],{},"Three choices keep this safe. The pulse changes size and a translucent ring rather than flipping the badge between light and dark, so the luminance change is small. The duration is long — 1.2 seconds per direction — so the rate is far under one cycle per second. And the iteration count is 4 — two full pulses — so the animation stops after about five seconds instead of running forever. An even count with ",[18,901,158],{}," also ends on the ",[18,904,905],{},"from"," keyframe, so the badge settles back at its normal size rather than staying enlarged.",[34,908,910],{"id":909},"the-key-technique-animate-shape-and-position-not-luminance","The key technique: animate shape and position, not luminance",[14,912,913],{},"The safest attention cues avoid large luminance swings altogether. Movement, scale, and a change in an outline or border draw the eye without the rapid light-dark alternation that defines a flash.",[66,915,73,918,73,921,73,924,73,927,73,936,73,939,73,945,73,949,73,954,73,958,73,962,73,965,73,968,73,971],{"viewBox":916,"role":69,"ariaLabel":917,"xmlns":71,"style":72},"0 0 720 260","Comparison of attention cues: risky ones flip brightness, like a strobing background or blinking text; safer ones animate scale, a soft ring, or a single slide-in",[75,919,920],{},"Risky cues versus safer cues",[79,922,923],{},"Left column lists risky cues: a background alternating between white and black, blinking text, and a strobing red border. Right column lists safer cues: a slow scale pulse, a fading ring that expands outward, and a one-time slide-in with no repetition. The safer cues change shape or position rather than overall brightness.",[83,925,926],{"textAnchor":85,"x":86,"y":87,"style":88},"Change shape, not brightness",[928,929],"rect",{"x":930,"y":931,"width":932,"height":933,"rx":934,"fill":96,"opacity":935},"40","50","300","180","10","0.08",[928,937],{"x":125,"y":931,"width":932,"height":933,"rx":934,"fill":107,"opacity":938},"0.2",[83,940,944],{"textAnchor":85,"x":941,"y":942,"style":943},"190","80","text-anchor:middle;fill:currentColor;font:600 14px sans-serif","Risky",[83,946,948],{"textAnchor":85,"x":947,"y":942,"style":943},"530","Safer",[83,950,953],{"textAnchor":85,"x":941,"y":951,"style":952},"118","text-anchor:middle;fill:currentColor;font:13px sans-serif","background black ↔ white",[83,955,957],{"textAnchor":85,"x":941,"y":956,"style":952},"152","blinking text (steps)",[83,959,961],{"textAnchor":85,"x":941,"y":960,"style":952},"186","strobing saturated red",[83,963,964],{"textAnchor":85,"x":947,"y":951,"style":952},"slow scale pulse",[83,966,967],{"textAnchor":85,"x":947,"y":956,"style":952},"fading ring, finite count",[83,969,970],{"textAnchor":85,"x":947,"y":960,"style":952},"one-time slide-in",[83,972,974],{"textAnchor":85,"x":86,"y":973,"style":127},"254","Low contrast, slow and finite beats bright, fast and infinite.",[14,976,977],{},"Red deserves special mention. Saturated red flashing is more likely to provoke seizures than other colours at the same luminance change, which is why it has its own threshold. Error states are the usual place designers reach for a red blink. A red border that appears and stays, with an icon and a message, communicates the error better than a blinking one and carries no risk.",[34,979,981],{"id":980},"audit-patterns-that-slip-through","Audit patterns that slip through",[14,983,984],{},"Flashing rarely comes from a deliberate strobe. More often it emerges from ordinary code:",[161,986,987,993,999,1010],{},[164,988,989,992],{},[145,990,991],{},"Rapid state toggles."," A hover effect that inverts a large card's colours, on a grid where moving the mouse crosses several cards per second, produces a sequence of flashes across the page.",[164,994,995,998],{},[145,996,997],{},"Loading shimmers with high contrast."," A skeleton shimmer that sweeps a bright band across a dark surface quickly can approach flash territory when many skeletons animate in sync over a large area.",[164,1000,1001,1004,1005,1009],{},[145,1002,1003],{},"Video and GIF backgrounds."," CSS cannot inspect media content. Autoplaying backgrounds need review of the media itself, and a pause control, as described in ",[23,1006,1008],{"href":1007},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fpause-controls-for-looping-animations\u002F","Pause Controls for Looping Animations",".",[164,1011,1012,1015],{},[145,1013,1014],{},"Theme switches."," Toggling from a dark to a light theme swaps luminance across the entire viewport. Once is fine; a toggle that can be spammed, or an automatic theme flip on scroll, is not.",[34,1017,1019],{"id":1018},"designing-sale-banners-and-alerts-without-strobing","Designing sale banners and alerts without strobing",[14,1021,1022],{},"Marketing requests for \"something that really grabs attention\" are the most common source of dangerous flashing. Offer alternatives that deliver the goal. A banner can slide in once from the top and stay; a countdown can tick with numbers changing in place, which changes a small area of text rather than a large block of luminance; a price can be emphasised with a static colour block and size rather than a blinking background. If a repeating effect is truly required, cap it: a slow shimmer that runs once per page view, or a pulse with a finite iteration count, keeps attention without continuous stimulation. These choices also satisfy WCAG 2.2.2, which requires a way to pause any movement lasting more than five seconds.",[34,1024,1026],{"id":1025},"reduced-motion-is-an-extra-layer-not-the-fix","Reduced motion is an extra layer, not the fix",[14,1028,1029,1030,1033,1034,1038],{},"It is tempting to wrap risky animations in ",[18,1031,1032],{},"@media (prefers-reduced-motion: no-preference)"," and consider the job done. That is not sufficient. Many people with photosensitive epilepsy have never changed that operating system setting, and some do not know they are photosensitive until a seizure occurs. WCAG 2.3.1 applies to every user regardless of preferences. Keep flashing below the thresholds for everyone, and then use the reduced-motion query to remove remaining non-essential motion for people who asked for less. ",[23,1035,1037],{"href":1036},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria\u002F","WCAG Motion Success Criteria"," sets the criteria side by side.",[34,1040,1042],{"id":1041},"browser-support","Browser support",[14,1044,1045,1046,1049,1050,1053,1054,1056,1057,1060],{},"Everything on this page uses long-established features: ",[18,1047,1048],{},"@keyframes"," is supported in Chrome 43+, Edge 12+, Firefox 16+ and Safari 9+, and ",[18,1051,1052],{},"prefers-reduced-motion"," in Chrome 74+, Edge 79+, Firefox 63+ and Safari 10.1+. The standalone ",[18,1055,673],{}," property used in the implementation is supported in the same versions as ",[18,1058,1059],{},"translate",": Chrome and Edge 104+, Firefox 72+ and Safari 14.1+.",[34,1062,1064],{"id":1063},"faq","FAQ",[14,1066,1067,1070],{},[145,1068,1069],{},"What is the three flashes rule?","\nWCAG 2.3.1 requires that nothing flashes more than three times in any one-second period, unless the flashing is below the general and red flash thresholds. Staying at or under three flashes per second is the simplest way to comply.",[14,1072,1073,1076],{},[145,1074,1075],{},"What counts as a flash in CSS?","\nA pair of opposing changes in relative luminance large enough to cross the threshold, such as a bright element turning dark and back. Blinking, strobing borders, alternating backgrounds and fast opacity toggles on high-contrast content can all be flashes.",[14,1078,1079,1082],{},[145,1080,1081],{},"Is a small flashing element safe?","\nArea matters: flashing that covers only a small part of the screen can fall below the general flash threshold. But viewing distance and screen size vary, so area alone is a weak safeguard. Slow, low-contrast motion is safer than relying on small size.",[14,1084,1085,1088],{},[145,1086,1087],{},"Does prefers-reduced-motion cover flashing?","\nNot reliably. Photosensitive users may not have set it, and WCAG's flash requirement applies regardless of preferences. Flashing above the thresholds must be avoided for everyone; reduced motion is an extra layer, not the fix.",[34,1090,1092],{"id":1091},"related","Related",[161,1094,1095,1100,1105,1112],{},[164,1096,1097,1099],{},[23,1098,26],{"href":25}," — the parent guide.",[164,1101,1102,1104],{},[23,1103,1037],{"href":1036}," — 2.2.2, 2.3.1 and 2.3.3 together.",[164,1106,1107,1111],{},[23,1108,1110],{"href":1109},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns\u002F","Vestibular-Safe Animation Patterns"," — the other major motion sensitivity.",[164,1113,1114,1118],{},[23,1115,1117],{"href":1116},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations\u002F","Choosing Animation Durations"," — timing that stays calm.",[326,1120,1121],{},"html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}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);}",{"title":210,"searchDepth":234,"depth":234,"links":1123},[1124,1125,1126,1127,1128,1129,1130,1131,1132,1133],{"id":36,"depth":234,"text":37},{"id":151,"depth":234,"text":152},{"id":195,"depth":234,"text":196},{"id":909,"depth":234,"text":910},{"id":980,"depth":234,"text":981},{"id":1018,"depth":234,"text":1019},{"id":1025,"depth":234,"text":1026},{"id":1041,"depth":234,"text":1042},{"id":1063,"depth":234,"text":1064},{"id":1091,"depth":234,"text":1092},"Keep CSS animations below WCAG flash thresholds: what counts as a flash, the three-per-second rule, area and red-flash limits, and safer attention cues.","md",{"pageTitle":5,"datePublished":1137,"dateModified":1137,"faq":1138},"2026-09-18",[1139,1141,1143,1145],{"q":1069,"a":1140},"WCAG 2.3.1 requires that nothing flashes more than three times in any one-second period, unless the flashing is below the general and red flash thresholds. Staying at or under three flashes per second is the simplest way to comply.",{"q":1075,"a":1142},"A pair of opposing changes in relative luminance large enough to cross the threshold, such as a bright element turning dark and back. Blinking, strobing borders, alternating backgrounds and fast opacity toggles on high-contrast content can all be flashes.",{"q":1081,"a":1144},"Area matters: flashing that covers only a small part of the screen can fall below the general flash threshold. But viewing distance and screen size vary, so area alone is a weak safeguard. Slow, low-contrast motion is safer than relying on small size.",{"q":1087,"a":1146},"Not reliably. Photosensitive users may not have set it, and WCAG's flash requirement applies regardless of preferences. Flashing above the thresholds must be avoided for everyone; reduced motion is an extra layer, not the fix.","\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds",{"title":5,"description":1134},"css-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds\u002Findex","Bl2i5OAKJlgXFqQmnbwupFG9JH8IKAzY1QmZjbwg1lw",[1152,1155,1156,1159,1162,1165,1168,1171,1174,1177,1180,1183,1186,1189,1192,1195,1198,1201,1204,1207,1210,1213,1216,1219,1222,1225,1228,1231,1234,1237,1240,1243,1246,1249,1252,1255,1258,1261,1264,1267,1270,1273,1276,1279,1282,1285,1288,1291,1294,1297,1300,1303,1306,1309,1312,1315,1318,1321,1324,1327,1330,1333,1336,1339,1342,1345,1348,1351,1354,1357,1360,1363,1366,1369,1372,1375,1378,1381,1384,1387,1390,1393,1396,1399,1402,1405,1408,1411,1414,1417,1420,1423,1426,1429,1431,1434,1437,1440,1443,1446,1449,1452,1455,1458,1461,1464,1467,1470,1473,1476,1479,1482,1485,1488,1491,1494,1497,1500,1503,1506,1509,1512,1515,1518,1521,1524,1527,1530,1533,1536,1539,1542,1545,1548,1551,1554,1557,1560,1563,1566,1569,1572,1575,1578,1581,1584,1587,1590,1593,1596,1599,1602,1605,1608,1611,1614,1617,1620,1623,1626,1629,1632,1635,1638,1641,1644,1647,1650,1653,1656,1659,1662,1665,1668,1671,1674,1677,1680,1683,1686,1689,1692,1695,1698,1701,1704,1707],{"path":1153,"title":1154},"\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":1147,"title":5},{"path":1157,"title":1158},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fforced-colors-mode-and-animations","Forced Colors Mode and Animations",{"path":1160,"title":1161},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":1163,"title":1164},"\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":1166,"title":1167},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":1169,"title":1170},"\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":1172,"title":1173},"\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":1175,"title":1176},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":1178,"title":1179},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":1181,"title":1182},"\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":1184,"title":1185},"\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":1187,"title":1188},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations","Clip-Path & Mask Animations: Animating Visibility Instead of Position",{"path":1190,"title":1191},"\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":1193,"title":1194},"\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":1196,"title":1197},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fanimating-gradients","Animating CSS Gradients: Smooth Colour Motion Without Jumps",{"path":1199,"title":1200},"\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":1202,"title":1203},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions","Color & Theme Transitions: Colour as Part of the Motion System",{"path":1205,"title":1206},"\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":1208,"title":1209},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fsmooth-theme-switching-transitions","Smooth Theme Switching: Crossfades, Circular Reveals and No Flash",{"path":1211,"title":1212},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":1214,"title":1215},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":1217,"title":1218},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Flayout-change-animations-at-container-breakpoints","Animating Changes at Container Breakpoints",{"path":1220,"title":1221},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries","Motion Driven by Container Style Queries",{"path":1223,"title":1224},"\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":1226,"title":1227},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":1229,"title":1230},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript","Controlling CSS Animations From JavaScript",{"path":1232,"title":1233},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":1235,"title":1236},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui","Interruptible UI: CSS Transitions vs WAAPI",{"path":1238,"title":1239},"\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":1241,"title":1242},"\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":1244,"title":1245},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values","Custom Property Fallbacks and Invalid Values",{"path":1247,"title":1248},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":1250,"title":1251},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":1253,"title":1254},"\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":1256,"title":1257},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components","Scoping Custom Properties to Components",{"path":1259,"title":1260},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":1262,"title":1263},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":1265,"title":1266},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions","Interrupted and Reversing Transitions: What Happens Mid-Flight",{"path":1268,"title":1269},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":1271,"title":1272},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-delay-choreography","Choreographing Motion With transition-delay",{"path":1274,"title":1275},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties","The transition Shorthand and Multiple Properties",{"path":1277,"title":1278},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1280,"title":1281},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fanimating-dialog-open-and-close","Animating \u003Cdialog> Open and Close: Both Directions, No Library",{"path":1283,"title":1284},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fbackdrop-animations","Animating ::backdrop: Fades and Blurs Behind Dialogs and Popovers",{"path":1286,"title":1287},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations","Dialog & Popover Animations: Motion for the Top Layer",{"path":1289,"title":1290},"\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":1292,"title":1293},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fpopover-entry-and-exit-transitions","Popover Menus That Animate From Their Anchor",{"path":1295,"title":1296},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations","Choosing Animation Durations: How Long Motion Should Last",{"path":1298,"title":1299},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fcubic-bezier-overshoot-and-anticipation","Overshoot and Anticipation With cubic-bezier(): Motion With Character",{"path":1301,"title":1302},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fentry-vs-exit-easing","Entry vs Exit Easing: Different Curves for Arriving and Leaving",{"path":1304,"title":1305},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design","Easing & Motion Design: Making CSS Motion Feel Intentional",{"path":1307,"title":1308},"\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":1310,"title":1311},"\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":1313,"title":1314},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1316,"title":1317},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fbutton-press-and-active-states","Button Press and  States",{"path":1319,"title":1320},"\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":1322,"title":1323},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1325,"title":1326},"\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":1328,"title":1329},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1331,"title":1332},"\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":1334,"title":1335},"\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":1337,"title":1338},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1340,"title":1341},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-composition-and-stacking","Stacking Animations With animation-composition",{"path":1343,"title":1344},"\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":1346,"title":1347},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1349,"title":1350},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1352,"title":1353},"\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":1355,"title":1356},"\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":1358,"title":1359},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1361,"title":1362},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fmulti-step-keyframes-and-per-keyframe-easing","Multi-Step Keyframes and Per-Keyframe Easing",{"path":1364,"title":1365},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1367,"title":1368},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fanimating-box-shadow-and-filters-cheaply","Animating box-shadow and Filters Cheaply",{"path":1370,"title":1371},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcontain-property-for-animation-performance","The contain Property for Animation Performance",{"path":1373,"title":1374},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcss-triggers-layout-paint-composite","Layout, Paint and Composite: What Triggers What",{"path":1376,"title":1377},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1379,"title":1380},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1382,"title":1383},"\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":1385,"title":1386},"\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":1388,"title":1389},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1391,"title":1392},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1394,"title":1395},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-parallax-effects","Scroll-Driven Parallax Effects in CSS",{"path":1397,"title":1398},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1400,"title":1401},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1403,"title":1404},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Ftimeline-scope-for-cross-element-animations","timeline-scope for Cross-Element Animations",{"path":1406,"title":1407},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fview-timeline-and-animation-range","View Timelines and animation-range",{"path":1409,"title":1410},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fcross-document-view-transitions","Cross-Document View Transitions",{"path":1412,"title":1413},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1415,"title":1416},"\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":1418,"title":1419},"\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":1421,"title":1422},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-types-and-classes","View Transition Types and Classes",{"path":1424,"title":1425},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-for-list-reordering","View Transitions for List Reordering",{"path":1427,"title":1428},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":353,"title":1430},"Modern CSS Layouts & Micro-Interactions",{"path":1432,"title":1433},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1435,"title":1436},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1438,"title":1439},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-size-for-matching-widths","anchor-size(): Overlays That Match Their Trigger's Size",{"path":1441,"title":1442},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1444,"title":1445},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1447,"title":1448},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-light-dismiss-and-stacking","Popover Light Dismiss, Nesting and Stacking",{"path":1450,"title":1451},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fposition-area-grid-explained","position-area: The Anchor Placement Grid",{"path":1453,"title":1454},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fcontainer-query-polyfill-tradeoffs","Container Query Polyfills: What They Cost and When to Skip Them",{"path":1456,"title":1457},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1459,"title":1460},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1462,"title":1463},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1465,"title":1466},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fintrinsic-layout-fallbacks-without-queries","Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query",{"path":1468,"title":1469},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ftesting-fallbacks-without-old-browsers","Testing CSS Fallbacks Without an Old Browser",{"path":1471,"title":1472},"\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":1474,"title":1475},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-range-and-logic-operators","Container Query Range Syntax and Logic Operators",{"path":1477,"title":1478},"\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":1480,"title":1481},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1483,"title":1484},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1486,"title":1487},"\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":1489,"title":1490},"\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":1492,"title":1493},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1495,"title":1496},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1498,"title":1499},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1501,"title":1502},"\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":1504,"title":1505},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-auto-flow-dense-packing","grid-auto-flow: dense for Packed Layouts",{"path":1507,"title":1508},"\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":1510,"title":1511},"\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":1513,"title":1514},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1516,"title":1517},"\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":1519,"title":1520},"\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":1522,"title":1523},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1525,"title":1526},"\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":1528,"title":1529},"\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":1531,"title":1532},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-grow-and-flex-shrink-explained","flex-grow and flex-shrink Explained",{"path":1534,"title":1535},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-wrap-intrinsic-responsive-rows","Breakpoint-Free Responsive Rows With flex-wrap and flex-basis",{"path":1537,"title":1538},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflexbox-gap-and-spacing","Flexbox gap vs Margins: Spacing Items Without Edge Hacks",{"path":1540,"title":1541},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns","Flexbox Layout Patterns: One-Dimensional Layout for Real Components",{"path":1543,"title":1544},"\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":1546,"title":1547},"\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":1549,"title":1550},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fdebugging-clamp-values","Debugging clamp(): Values That Are Ignored, Stuck or Never Fluid",{"path":1552,"title":1553},"\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":1555,"title":1556},"\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":1558,"title":1559},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1561,"title":1562},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1564,"title":1565},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1567,"title":1568},"\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":1570,"title":1571},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1573,"title":1574},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1576,"title":1577},"\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":1579,"title":1580},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1582,"title":1583},"\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":1585,"title":1586},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1588,"title":1589},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fobject-fit-and-object-position","object-fit and object-position: Images That Fit Any Box",{"path":1591,"title":1592},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1594,"title":1595},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1597,"title":1598},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1600,"title":1601},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcss-scope-for-component-styles","@scope for Component Styles: Short Selectors That Cannot Leak",{"path":1603,"title":1604},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1606,"title":1607},"\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":1609,"title":1610},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fwriting-a-minimal-modern-reset","Writing a Minimal Modern CSS Reset: Every Line Justified",{"path":1612,"title":1613},"\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":1615,"title":1616},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fempty-and-loading-states-with-has","Empty and Loading States With ()",{"path":1618,"title":1619},"\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":1621,"title":1622},"\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":1624,"title":1625},"\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":1627,"title":1628},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has","Parent-Aware Layouts With :has(): Letting Containers React to Their Contents",{"path":1630,"title":1631},"\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":1633,"title":1634},"\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":1636,"title":1637},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1639,"title":1640},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":1642,"title":1643},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":1645,"title":1646},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":1648,"title":1649},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-hero-sections-with-container-queries","Responsive Hero Sections With Container Queries",{"path":1651,"title":1652},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":1654,"title":1655},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-pricing-tables","Responsive Pricing Tables: Aligned Features, a Clear Recommendation, Any Width",{"path":1657,"title":1658},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Ftabs-that-become-accordions","Tabs That Become an Accordion: One Component, Two Layouts",{"path":1660,"title":1661},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap","A CSS-Only Carousel With Scroll Snap",{"path":1663,"title":1664},"\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":1666,"title":1667},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts","Scroll Snap & Overflow Layouts: Designing Components That Scroll on Purpose",{"path":1669,"title":1670},"\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":1672,"title":1673},"\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":1675,"title":1676},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcombining-size-and-style-queries","Combining Size and Style Container Queries",{"path":1678,"title":1679},"\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":1681,"title":1682},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":1684,"title":1685},"\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":1687,"title":1688},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-component-variants","Component Variants With Style Queries: One Token, Many Looks",{"path":1690,"title":1691},"\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":1693,"title":1694},"\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":1696,"title":1697},"\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":1699,"title":1700},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout","Viewport Units & Mobile Layout: Designing for the Screen You Actually Get",{"path":1702,"title":1703},"\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":1705,"title":1706},"\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":1708,"title":1709},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fvirtual-keyboard-and-interactive-widget","Layouts That Survive the Virtual Keyboard",{"title":1711,"caption":1712,"height":1713,"html":1714,"css":1715},"An attention cue that stays below flash thresholds","Hover the panel to replay. The badge pulses twice with a slow scale and fading ring, never flipping between light and dark. The \"don't\" pattern is described, not shown.",200,"\n\u003Cdiv class=\"panel\">\n  \u003Cp class=\"row\">Inbox \u003Cspan class=\"badge badge--new\">3\u003C\u002Fspan>\u003C\u002Fp>\n  \u003Cp class=\"dont\">\u003Cstrong>Don't:\u003C\u002Fstrong> \u003Ccode>animation: blink 166ms steps(1) infinite alternate\u003C\u002Fcode> on a large dark\u002Flight area — three hard flashes every second, forever.\u003C\u002Fp>\n\u003C\u002Fdiv>","\n.panel { padding: 1rem; display: grid; gap: 0.75rem; }\n.row { margin: 0; font-size: 1.05rem; display: flex; align-items: center; gap: 0.5rem; }\n.dont { margin: 0; font-size: 0.85rem; color: var(--demo-muted); border-inline-start: 3px solid var(--demo-border); padding-inline-start: 0.75rem; }\n.badge { display: inline-grid; place-items: center; min-inline-size: 1.5rem; block-size: 1.5rem; padding-inline: 0.4rem; border-radius: 999px; background: #2563eb; color: #fff; font-size: 0.8rem; font-weight: 700; }\n.badge--new { animation: attention 1.2s ease-in-out 4 alternate both; }\n.panel:hover .badge--new { animation-name: attention-replay; }\n@keyframes attention { from { box-shadow: 0 0 0 0 rgb(37 99 235 \u002F 0.45); scale: 1; } to { box-shadow: 0 0 0 6px rgb(37 99 235 \u002F 0); scale: 1.08; } }\n@keyframes attention-replay { from { box-shadow: 0 0 0 0 rgb(37 99 235 \u002F 0.45); scale: 1; } to { box-shadow: 0 0 0 6px rgb(37 99 235 \u002F 0); scale: 1.08; } }\n@media (prefers-reduced-motion: reduce) { .badge--new, .panel:hover .badge--new { animation: none; outline: 2px solid var(--demo-accent); outline-offset: 2px; } }",1789717746763]