[{"data":1,"prerenderedAt":1445},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui":3,"content-all-pages":880,"live-demo:interrupt-compare":1439},{"id":4,"title":5,"body":6,"description":863,"extension":864,"meta":865,"navigation":181,"path":876,"seo":877,"stem":878,"__hash__":879},"content\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui\u002Findex.md","Interruptible UI: CSS Transitions vs WAAPI",{"type":7,"value":8,"toc":852},"minimark",[9,13,28,33,40,46,57,142,146,149,153,480,487,491,503,587,599,603,606,644,736,745,749,757,761,764,768,788,792,798,804,810,816,820,849],[10,11,5],"h1",{"id":12},"interruptible-ui-css-transitions-vs-waapi",[14,15,16,17,22,23,27],"p",{},"Interfaces are interrupted constantly. A user opens a menu and closes it before it finishes opening; hovers across a row of cards; drags a sheet halfway, lets go, then grabs it again. An animation system that only looks good when left alone looks broken in real use: elements jump, restart from the beginning, or finish an outdated motion before starting the new one. The three animation tools on the web — CSS transitions, CSS keyframe animations and the Web Animations API — handle interruption very differently. This page compares them and shows which to reach for when motion must be interruptible. It belongs to ",[18,19,21],"a",{"href":20},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002F","CSS Animation vs Web Animations API"," in the ",[18,24,26],{"href":25},"\u002Fcss-only-micro-interactions-animations\u002F","CSS-Only Micro-Interactions & Animations"," guide.",[29,30,32],"h2",{"id":31},"three-behaviours-under-interruption","Three behaviours under interruption",[14,34,35,39],{},[36,37,38],"strong",{},"Transitions retarget."," A transition runs from the current computed value to the new target. If the target changes mid-flight, a new transition starts from wherever the element is now. The motion turns around smoothly, with a proportionally shortened duration when it reverses to the original value.",[14,41,42,45],{},[36,43,44],{},"Keyframe animations restart or snap."," A keyframe animation always runs from its first keyframe. If the class that applies it is removed mid-flight, the element snaps to its unanimated style immediately; if another animation is applied, that one starts from its own first keyframe, not from where the element currently is.",[14,47,48,51,52,56],{},[36,49,50],{},"WAAPI does what you tell it."," An ",[53,54,55],"code",{},"element.animate()"," call can start from any value, including the current on-screen one read from the running animation. That flexibility is what gesture-driven and physics-based motion needs, at the cost of writing the logic yourself.",[58,59,65,66,65,70,65,74,65,82,65,91,65,99,65,105,65,111,65,116,65,121,65,127,65,132,65,137],"svg",{"viewBox":60,"role":61,"ariaLabel":62,"xmlns":63,"style":64},"0 0 720 300","img","Position over time when a hover ends halfway: the transition turns around smoothly, the keyframe animation snaps back, and WAAPI continues from the current point along any chosen path","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[67,68,69],"title",{},"What happens at the moment of interruption",[71,72,73],"desc",{},"Three position-over-time curves that share a rising first half. At the interruption line: the transition curve bends and descends smoothly back to zero; the keyframe animation curve drops vertically to zero, a snap; the Web Animations API curve continues from the current point along a custom path, for example carrying momentum a little further before settling.",[75,76,81],"text",{"textAnchor":77,"x":78,"y":79,"style":80},"middle","360","26","text-anchor:middle;fill:currentColor;font:700 17px sans-serif","Interrupted at the halfway mark",[83,84],"line",{"x1":85,"y1":86,"x2":87,"y2":86,"stroke":88,"strokeWidth":89,"opacity":90},"80","240","660","currentColor","1.5","0.6",[83,92],{"x1":93,"y1":94,"x2":93,"y2":95,"stroke":88,"strokeWidth":89,"strokeDashArray":96,"opacity":90},"300","50","250",[97,98],"5","4",[100,101],"path",{"d":102,"fill":103,"stroke":104,"strokeWidth":98},"M80 240 C160 240 220 150 300 140 C360 132 400 240 460 240","none","#7aa2ff",[100,106],{"d":107,"fill":103,"stroke":88,"strokeWidth":108,"strokeDashArray":109},"M80 240 C160 240 220 150 300 140 V240","2",[110,110],"3",[100,112],{"d":113,"fill":103,"stroke":104,"strokeWidth":108,"strokeDashArray":114},"M300 140 C340 128 380 118 420 130 C480 150 540 240 620 240",[115,97],"10",[75,117,120],{"textAnchor":77,"x":93,"y":118,"style":119},"44","text-anchor:middle;fill:currentColor;font:12px sans-serif","hover ends",[75,122,126],{"textAnchor":123,"x":124,"y":124,"style":125},"start","100","text-anchor:start;fill:currentColor;font:12px sans-serif","solid: transition turns around",[75,128,131],{"textAnchor":123,"x":129,"y":130,"style":125},"310","200","dotted: keyframes snap",[75,133,136],{"textAnchor":123,"x":134,"y":135,"style":125},"430","104","dashed: WAAPI continues",[75,138,141],{"textAnchor":77,"x":139,"y":140,"style":119},"370","272","time",[29,143,145],{"id":144},"the-complete-implementation","The complete implementation",[14,147,148],{},"Hover each track in the demo and leave it again before the box arrives. The first uses a transition and turns around smoothly. The second applies a keyframe animation on hover and snaps back when the pointer leaves.",[150,151],"live-demo",{"name":152},"interrupt-compare",[154,155,160],"pre",{"className":156,"code":157,"language":158,"meta":159,"style":159},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F* Hover the track, not the moving box, so the box can move\n   away from the pointer without ending the hover. *\u002F\n\n\u002F* Interruptible: a transition retargets from the current value. *\u002F\n.box--transition {\n  transition: translate 600ms cubic-bezier(0.2, 0, 0, 1);\n}\n.track:hover .box--transition,\n.track:focus-within .box--transition {\n  translate: 8rem 0;\n}\n\n\u002F* Not interruptible: the animation exists only while hovered. *\u002F\n.track:hover .box--keyframes,\n.track:focus-within .box--keyframes {\n  animation: slide 600ms cubic-bezier(0.2, 0, 0, 1) forwards;\n}\n@keyframes slide {\n  to { translate: 8rem 0; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .box--transition { transition-duration: 1ms; }\n  .track:hover .box--keyframes,\n  .track:focus-within .box--keyframes { animation-duration: 1ms; }\n}\n","css","",[53,161,162,170,176,183,189,200,243,249,261,271,292,297,302,308,318,327,366,371,383,406,411,416,425,444,454,475],{"__ignoreMap":159},[163,164,166],"span",{"class":83,"line":165},1,[163,167,169],{"class":168},"sLBg1","\u002F* Hover the track, not the moving box, so the box can move\n",[163,171,173],{"class":83,"line":172},2,[163,174,175],{"class":168},"   away from the pointer without ending the hover. *\u002F\n",[163,177,179],{"class":83,"line":178},3,[163,180,182],{"emptyLinePlaceholder":181},true,"\n",[163,184,186],{"class":83,"line":185},4,[163,187,188],{"class":168},"\u002F* Interruptible: a transition retargets from the current value. *\u002F\n",[163,190,192,196],{"class":83,"line":191},5,[163,193,195],{"class":194},"s-5SL",".box--transition",[163,197,199],{"class":198},"suds8"," {\n",[163,201,203,206,209,212,216,219,222,225,228,231,233,235,237,240],{"class":83,"line":202},6,[163,204,205],{"class":194},"  transition",[163,207,208],{"class":198},": translate ",[163,210,211],{"class":194},"600",[163,213,215],{"class":214},"sHUrx","ms",[163,217,218],{"class":194}," cubic-bezier",[163,220,221],{"class":198},"(",[163,223,224],{"class":194},"0.2",[163,226,227],{"class":198},", ",[163,229,230],{"class":194},"0",[163,232,227],{"class":198},[163,234,230],{"class":194},[163,236,227],{"class":198},[163,238,239],{"class":194},"1",[163,241,242],{"class":198},");\n",[163,244,246],{"class":83,"line":245},7,[163,247,248],{"class":198},"}\n",[163,250,252,255,258],{"class":83,"line":251},8,[163,253,254],{"class":194},".track:hover",[163,256,257],{"class":194}," .box--transition",[163,259,260],{"class":198},",\n",[163,262,264,267,269],{"class":83,"line":263},9,[163,265,266],{"class":194},".track:focus-within",[163,268,257],{"class":194},[163,270,199],{"class":198},[163,272,274,277,280,283,286,289],{"class":83,"line":273},10,[163,275,276],{"class":194},"  translate",[163,278,279],{"class":198},": ",[163,281,282],{"class":194},"8",[163,284,285],{"class":214},"rem",[163,287,288],{"class":194}," 0",[163,290,291],{"class":198},";\n",[163,293,295],{"class":83,"line":294},11,[163,296,248],{"class":198},[163,298,300],{"class":83,"line":299},12,[163,301,182],{"emptyLinePlaceholder":181},[163,303,305],{"class":83,"line":304},13,[163,306,307],{"class":168},"\u002F* Not interruptible: the animation exists only while hovered. *\u002F\n",[163,309,311,313,316],{"class":83,"line":310},14,[163,312,254],{"class":194},[163,314,315],{"class":194}," .box--keyframes",[163,317,260],{"class":198},[163,319,321,323,325],{"class":83,"line":320},15,[163,322,266],{"class":194},[163,324,315],{"class":194},[163,326,199],{"class":198},[163,328,330,333,336,338,340,342,344,346,348,350,352,354,356,358,361,364],{"class":83,"line":329},16,[163,331,332],{"class":194},"  animation",[163,334,335],{"class":198},": slide ",[163,337,211],{"class":194},[163,339,215],{"class":214},[163,341,218],{"class":194},[163,343,221],{"class":198},[163,345,224],{"class":194},[163,347,227],{"class":198},[163,349,230],{"class":194},[163,351,227],{"class":198},[163,353,230],{"class":194},[163,355,227],{"class":198},[163,357,239],{"class":194},[163,359,360],{"class":198},") ",[163,362,363],{"class":194},"forwards",[163,365,291],{"class":198},[163,367,369],{"class":83,"line":368},17,[163,370,248],{"class":198},[163,372,374,377,381],{"class":83,"line":373},18,[163,375,376],{"class":214},"@keyframes",[163,378,380],{"class":379},"soyes"," slide",[163,382,199],{"class":198},[163,384,386,389,392,395,397,399,401,403],{"class":83,"line":385},19,[163,387,388],{"class":194},"  to",[163,390,391],{"class":198}," { ",[163,393,394],{"class":194},"translate",[163,396,279],{"class":198},[163,398,282],{"class":194},[163,400,285],{"class":214},[163,402,288],{"class":194},[163,404,405],{"class":198},"; }\n",[163,407,409],{"class":83,"line":408},20,[163,410,248],{"class":198},[163,412,414],{"class":83,"line":413},21,[163,415,182],{"emptyLinePlaceholder":181},[163,417,419,422],{"class":83,"line":418},22,[163,420,421],{"class":214},"@media",[163,423,424],{"class":198}," (prefers-reduced-motion: reduce) {\n",[163,426,428,431,433,436,438,440,442],{"class":83,"line":427},23,[163,429,430],{"class":194},"  .box--transition",[163,432,391],{"class":198},[163,434,435],{"class":194},"transition-duration",[163,437,279],{"class":198},[163,439,239],{"class":194},[163,441,215],{"class":214},[163,443,405],{"class":198},[163,445,447,450,452],{"class":83,"line":446},24,[163,448,449],{"class":194},"  .track:hover",[163,451,315],{"class":194},[163,453,260],{"class":198},[163,455,457,460,462,464,467,469,471,473],{"class":83,"line":456},25,[163,458,459],{"class":194},"  .track:focus-within",[163,461,315],{"class":194},[163,463,391],{"class":198},[163,465,466],{"class":194},"animation-duration",[163,468,279],{"class":198},[163,470,239],{"class":194},[163,472,215],{"class":214},[163,474,405],{"class":198},[163,476,478],{"class":83,"line":477},26,[163,479,248],{"class":198},[14,481,482,483,486],{},"The keyframe version has no \"leave\" motion at all: when ",[53,484,485],{},":hover"," stops matching, the animation is removed and the element's style reverts instantly. You could add a second animation for leaving, but it would start from its own first keyframe — the fully moved position — even if the entering animation had only got a quarter of the way. That jump is the fundamental problem with using keyframes for state changes. Notice also that the demo hovers a track rather than the moving box itself. If the hover target were the box, sliding it away from the pointer would end the hover mid-move, and the transition version would flicker back and forth — an interruption loop the user never asked for.",[29,488,490],{"id":489},"the-key-technique-states-with-transitions-sequences-with-keyframes","The key technique: states with transitions, sequences with keyframes",[14,492,493,494,498,499,502],{},"The dividing line is simple. When motion expresses a change between two ",[495,496,497],"em",{},"states"," — open and closed, hovered and not, selected and not — use a transition, because states can change at any moment and transitions handle that for free. When motion is a self-contained ",[495,500,501],{},"sequence"," that plays through once — an attention nudge, a loading loop, a celebratory burst — use keyframes, because sequences are rarely interrupted and keyframes express multi-step motion better.",[58,504,65,507,65,510,65,513,65,516,65,523,65,527,65,531,65,536,65,539,65,543,65,547,65,551,65,555,65,559,65,562,65,565,65,568,65,571,65,574,65,577,65,580,65,583],{"viewBox":505,"role":61,"ariaLabel":506,"xmlns":63,"style":64},"0 0 720 260","Decision guide: state changes use transitions; one-off sequences use keyframes; gesture-driven or physics-based motion that must continue from the current value uses the Web Animations API",[67,508,509],{},"Pick the tool by how motion will be interrupted",[71,511,512],{},"Three columns. Transitions: open and close, hover and focus, toggles, anything that can reverse at any moment. Keyframes: loaders, attention cues, entrance sequences that play once. Web Animations API: drag and release, momentum and springs, coordinated interruption of several elements.",[75,514,515],{"textAnchor":77,"x":78,"y":79,"style":80},"Match the tool to the interruption",[517,518],"rect",{"x":519,"y":94,"width":520,"height":521,"rx":115,"fill":104,"opacity":522},"30","210","170","0.3",[517,524],{"x":525,"y":94,"width":520,"height":521,"rx":115,"fill":104,"opacity":526},"255","0.15",[517,528],{"x":529,"y":94,"width":520,"height":521,"rx":115,"fill":88,"opacity":530},"480","0.1",[75,532,535],{"textAnchor":77,"x":533,"y":85,"style":534},"135","text-anchor:middle;fill:currentColor;font:600 14px sans-serif","Transitions",[75,537,538],{"textAnchor":77,"x":78,"y":85,"style":534},"Keyframes",[75,540,542],{"textAnchor":77,"x":541,"y":85,"style":534},"585","Web Animations API",[75,544,546],{"textAnchor":77,"x":533,"y":545,"style":119},"114","open and close",[75,548,550],{"textAnchor":77,"x":533,"y":549,"style":119},"140","hover and focus",[75,552,554],{"textAnchor":77,"x":533,"y":553,"style":119},"166","toggles, selection",[75,556,558],{"textAnchor":77,"x":533,"y":557,"style":119},"192","reversible at any time",[75,560,561],{"textAnchor":77,"x":78,"y":545,"style":119},"loaders and loops",[75,563,564],{"textAnchor":77,"x":78,"y":549,"style":119},"attention cues",[75,566,567],{"textAnchor":77,"x":78,"y":553,"style":119},"entrance sequences",[75,569,570],{"textAnchor":77,"x":78,"y":557,"style":119},"play through once",[75,572,573],{"textAnchor":77,"x":541,"y":545,"style":119},"drag and release",[75,575,576],{"textAnchor":77,"x":541,"y":549,"style":119},"momentum, springs",[75,578,579],{"textAnchor":77,"x":541,"y":553,"style":119},"coordinated handoffs",[75,581,582],{"textAnchor":77,"x":541,"y":557,"style":119},"start from live value",[75,584,586],{"textAnchor":77,"x":78,"y":585,"style":119},"248","Most interface motion belongs in the first column.",[14,588,589,590,593,594,598],{},"Entry animations are a special case. Since ",[53,591,592],{},"@starting-style"," arrived, elements appearing in the DOM can use transitions for their entry, which makes their exit interruptible too: a popover closed while still opening reverses from its current position. ",[18,595,597],{"href":596},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations\u002F","Starting-Style Entry Animations"," covers the technique; it is usually better than a keyframe entry for anything the user can dismiss.",[29,600,602],{"id":601},"when-the-web-animations-api-earns-its-place","When the Web Animations API earns its place",[14,604,605],{},"Transitions retarget, but only along a fixed curve toward a new target, with no memory of speed. Three situations need more:",[607,608,609,620,634],"ol",{},[610,611,612,615,616,619],"li",{},[36,613,614],{},"Gestures with momentum."," When a user flings a bottom sheet, the release animation should start at the finger's velocity. A CSS transition always starts from rest. With WAAPI you read the current position, compute an easing or a ",[53,617,618],{},"linear()"," spring curve that matches the release velocity, and animate from there.",[610,621,622,625,626,629,630,633],{},[36,623,624],{},"Handing off between animations."," If an element is mid-way through one animation and must start a different one — not a reversal, a new path — WAAPI can read the current value with ",[53,627,628],{},"getComputedStyle",", call ",[53,631,632],{},"commitStyles()"," to freeze it into the inline style, cancel the old animation, and start the new one from exactly that point.",[610,635,636,639,640,643],{},[36,637,638],{},"Coordinated interruption."," When interrupting one element should also re-time others — a list where removing an item mid-animation must re-flow its neighbours — script needs to see and adjust every running animation, which ",[53,641,642],{},"getAnimations()"," makes possible.",[154,645,649],{"className":646,"code":647,"language":648,"meta":159,"style":159},"language-js shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F\u002F Hand off from a running animation to a new one without a jump.\nfunction retarget(el, running, keyframesTo, options) {\n  running.commitStyles();   \u002F\u002F write the current on-screen value inline\n  running.cancel();         \u002F\u002F stop the old animation\n  return el.animate(keyframesTo, options);  \u002F\u002F starts from the committed value\n}\n","js",[53,650,651,656,688,702,715,732],{"__ignoreMap":159},[163,652,653],{"class":83,"line":165},[163,654,655],{"class":168},"\u002F\u002F Hand off from a running animation to a new one without a jump.\n",[163,657,658,661,665,667,670,672,675,677,680,682,685],{"class":83,"line":172},[163,659,660],{"class":214},"function",[163,662,664],{"class":663},"sKwhi"," retarget",[163,666,221],{"class":198},[163,668,669],{"class":379},"el",[163,671,227],{"class":198},[163,673,674],{"class":379},"running",[163,676,227],{"class":198},[163,678,679],{"class":379},"keyframesTo",[163,681,227],{"class":198},[163,683,684],{"class":379},"options",[163,686,687],{"class":198},") {\n",[163,689,690,693,696,699],{"class":83,"line":178},[163,691,692],{"class":198},"  running.",[163,694,695],{"class":663},"commitStyles",[163,697,698],{"class":198},"();   ",[163,700,701],{"class":168},"\u002F\u002F write the current on-screen value inline\n",[163,703,704,706,709,712],{"class":83,"line":185},[163,705,692],{"class":198},[163,707,708],{"class":663},"cancel",[163,710,711],{"class":198},"();         ",[163,713,714],{"class":168},"\u002F\u002F stop the old animation\n",[163,716,717,720,723,726,729],{"class":83,"line":191},[163,718,719],{"class":214},"  return",[163,721,722],{"class":198}," el.",[163,724,725],{"class":663},"animate",[163,727,728],{"class":198},"(keyframesTo, options);  ",[163,730,731],{"class":168},"\u002F\u002F starts from the committed value\n",[163,733,734],{"class":83,"line":202},[163,735,248],{"class":198},[14,737,738,740,741,744],{},[53,739,632],{}," requires the element to be rendered and writes the animated properties into the ",[53,742,743],{},"style"," attribute. After the new animation finishes, remember that the inline style is still there; either commit the final value too or clean up the inline properties.",[29,746,748],{"id":747},"proportional-reversal-a-detail-transitions-get-right","Proportional reversal: a detail transitions get right",[14,750,751,752,756],{},"When a transition is interrupted and heads back to its original value, browsers shorten the new transition in proportion to how far the first had progressed. A 300ms opening transition interrupted after 60% of its progress reverses in roughly 180ms, not a full 300ms. Without this, quick hover-in, hover-out movements would feel sluggish, because every reversal would take the full duration regardless of how little distance remained. Keyframe animations and naive WAAPI code do not do this automatically; if you build interruption logic in script, scale the reverse duration by the progress yourself. ",[18,753,755],{"href":754},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions\u002F","Interrupted and Reversing Transitions"," shows the effect in detail.",[29,758,760],{"id":759},"testing-interruption-deliberately","Testing interruption deliberately",[14,762,763],{},"Interruption bugs hide in demos because demos are usually played through calmly. Make interruption part of reviewing any animation: toggle it twice quickly, hover in and out repeatedly, press a key while the previous press is still animating, and resize the window mid-transition. Slow the animation down with the DevTools Animations panel to see exactly what happens at the moment of interruption. A good result looks the same at every playback speed: the element always moves continuously from where it is, and never jumps to a position it was not at.",[29,765,767],{"id":766},"browser-support","Browser support",[14,769,770,771,774,775,778,779,781,782,784,785,787],{},"CSS transitions and keyframe animations are supported in every current browser; the ",[53,772,773],{},"transition"," shorthand dates from Chrome 26, Edge 12, Firefox 16 and Safari 9. The Web Animations API (",[53,776,777],{},"element.animate",") is supported in Chrome 36+, Edge 79+, Firefox 48+ and Safari 13.1+; newer members such as ",[53,780,632],{}," arrived in later versions, so check the specific methods you use. ",[53,783,592],{}," is supported in Chrome and Edge 117+, Firefox 129+ and Safari 17.5+, and ",[53,786,618],{}," easing in Chrome and Edge 113+, Firefox 112+ and Safari 17.2+.",[29,789,791],{"id":790},"faq","FAQ",[14,793,794,797],{},[36,795,796],{},"Why do CSS transitions handle interruption better than keyframe animations?","\nA transition always starts from the element's current computed value, so if the target changes mid-flight it turns around from wherever it is. A keyframe animation has fixed start and end keyframes; removing it snaps the element to its unanimated style and re-adding it restarts from the first keyframe.",[14,799,800,803],{},[36,801,802],{},"When do I need the Web Animations API for interruptions?","\nWhen the new animation must start from the current on-screen value and follow a path CSS cannot express, such as continuing a drag gesture with its velocity, or when several interrupted animations must be coordinated. WAAPI can read the current value and build a new animation from it.",[14,805,806,809],{},[36,807,808],{},"What does commitStyles() do?","\nIt writes an animation's current computed values into the element's inline style. Calling it before cancelling an animation freezes the element where it is, so a following animation can start from that point instead of jumping.",[14,811,812,815],{},[36,813,814],{},"Do interrupted transitions keep their full duration?","\nNo. When a transition reverses back toward its original value before finishing, browsers shorten the reverse duration in proportion to how far it had progressed, so a half-finished 300ms transition takes about 150ms to return.",[29,817,819],{"id":818},"related","Related",[821,822,823,828,835,842],"ul",{},[610,824,825,827],{},[18,826,21],{"href":20}," — the parent guide.",[610,829,830,834],{},[18,831,833],{"href":832},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript\u002F","Controlling CSS Animations From JavaScript"," — getAnimations() and the finished promise.",[610,836,837,841],{},[18,838,840],{"href":839},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwhen-to-use-javascript-animation\u002F","When to Use JavaScript Animation"," — the broader decision.",[610,843,844,848],{},[18,845,847],{"href":846},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Flinear-easing-function-for-springs\u002F","Spring and Bounce Easing With linear()"," — spring curves for release animations.",[743,850,851],{},"html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .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);}html pre.shiki code .sKwhi, html code.shiki .sKwhi{--shiki-default:#622CBC;--shiki-dark:#DBB7FF}",{"title":159,"searchDepth":172,"depth":172,"links":853},[854,855,856,857,858,859,860,861,862],{"id":31,"depth":172,"text":32},{"id":144,"depth":172,"text":145},{"id":489,"depth":172,"text":490},{"id":601,"depth":172,"text":602},{"id":747,"depth":172,"text":748},{"id":759,"depth":172,"text":760},{"id":766,"depth":172,"text":767},{"id":790,"depth":172,"text":791},{"id":818,"depth":172,"text":819},"Which animation tool handles interruption well: transitions that retarget, keyframes that snap, and when the Web Animations API is needed for gestures.","md",{"pageTitle":5,"datePublished":866,"dateModified":866,"faq":867},"2026-09-18",[868,870,872,874],{"q":796,"a":869},"A transition always starts from the element's current computed value, so if the target changes mid-flight it turns around from wherever it is. A keyframe animation has fixed start and end keyframes; removing it snaps the element to its unanimated style and re-adding it restarts from the first keyframe.",{"q":802,"a":871},"When the new animation must start from the current on-screen value and follow a path CSS cannot express, such as continuing a drag gesture with its velocity, or when several interrupted animations must be coordinated. WAAPI can read the current value and build a new animation from it.",{"q":808,"a":873},"It writes an animation's current computed values into the element's inline style. Calling it before cancelling an animation freezes the element where it is, so a following animation can start from that point instead of jumping.",{"q":814,"a":875},"No. When a transition reverses back toward its original value before finishing, browsers shorten the reverse duration in proportion to how far it had progressed, so a half-finished 300ms transition takes about 150ms to return.","\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui",{"title":5,"description":863},"css-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fwaapi-vs-css-for-interruptible-ui\u002Findex","5_Mtwlu0oHC35J2iK6gd4CloD-n-WoPoz04rwin5cxw",[881,884,887,890,893,896,899,902,905,908,911,914,917,920,923,926,929,932,935,938,941,944,947,950,953,956,959,961,964,965,968,971,974,977,980,983,986,989,992,995,998,1001,1004,1007,1010,1013,1016,1019,1022,1025,1028,1031,1034,1037,1040,1043,1046,1049,1052,1055,1058,1061,1064,1067,1070,1073,1076,1079,1082,1085,1088,1091,1094,1097,1100,1103,1106,1109,1112,1115,1118,1121,1124,1127,1130,1133,1136,1139,1142,1145,1148,1151,1154,1157,1160,1163,1166,1169,1172,1175,1178,1181,1184,1187,1190,1193,1196,1199,1202,1205,1208,1211,1214,1217,1220,1223,1226,1229,1232,1235,1238,1241,1244,1247,1250,1253,1256,1259,1262,1265,1268,1271,1274,1277,1280,1283,1286,1289,1292,1295,1298,1301,1304,1307,1310,1313,1316,1319,1322,1325,1328,1331,1334,1337,1340,1343,1346,1349,1352,1355,1358,1361,1364,1367,1370,1373,1376,1379,1382,1385,1388,1391,1394,1397,1400,1403,1406,1409,1412,1415,1418,1421,1424,1427,1430,1433,1436],{"path":882,"title":883},"\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":885,"title":886},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fflashing-content-and-seizure-thresholds","Flashing Content and Seizure Thresholds",{"path":888,"title":889},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fforced-colors-mode-and-animations","Forced Colors Mode and Animations",{"path":891,"title":892},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":894,"title":895},"\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":897,"title":898},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":900,"title":901},"\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":903,"title":904},"\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":906,"title":907},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":909,"title":910},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":912,"title":913},"\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":915,"title":916},"\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":918,"title":919},"\u002Fcss-only-micro-interactions-animations\u002Fclip-path-and-mask-animations","Clip-Path & Mask Animations: Animating Visibility Instead of Position",{"path":921,"title":922},"\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":924,"title":925},"\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":927,"title":928},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fanimating-gradients","Animating CSS Gradients: Smooth Colour Motion Without Jumps",{"path":930,"title":931},"\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":933,"title":934},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions","Color & Theme Transitions: Colour as Part of the Motion System",{"path":936,"title":937},"\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":939,"title":940},"\u002Fcss-only-micro-interactions-animations\u002Fcolor-and-theme-transitions\u002Fsmooth-theme-switching-transitions","Smooth Theme Switching: Crossfades, Circular Reveals and No Flash",{"path":942,"title":943},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":945,"title":946},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":948,"title":949},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Flayout-change-animations-at-container-breakpoints","Animating Changes at Container Breakpoints",{"path":951,"title":952},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fmotion-driven-by-container-style-queries","Motion Driven by Container Style Queries",{"path":954,"title":955},"\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":957,"title":958},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":960,"title":833},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api\u002Fcontrolling-css-animations-from-javascript",{"path":962,"title":963},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":876,"title":5},{"path":966,"title":967},"\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":969,"title":970},"\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":972,"title":973},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fcustom-property-fallbacks-and-invalid-values","Custom Property Fallbacks and Invalid Values",{"path":975,"title":976},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":978,"title":979},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":981,"title":982},"\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":984,"title":985},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Fscoping-custom-properties-to-components","Scoping Custom Properties to Components",{"path":987,"title":988},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":990,"title":991},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":993,"title":994},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Finterrupted-and-reversing-transitions","Interrupted and Reversing Transitions: What Happens Mid-Flight",{"path":996,"title":997},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":999,"title":1000},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-delay-choreography","Choreographing Motion With transition-delay",{"path":1002,"title":1003},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransition-shorthand-and-multiple-properties","The transition Shorthand and Multiple Properties",{"path":1005,"title":1006},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":1008,"title":1009},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fanimating-dialog-open-and-close","Animating \u003Cdialog> Open and Close: Both Directions, No Library",{"path":1011,"title":1012},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fbackdrop-animations","Animating ::backdrop: Fades and Blurs Behind Dialogs and Popovers",{"path":1014,"title":1015},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations","Dialog & Popover Animations: Motion for the Top Layer",{"path":1017,"title":1018},"\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":1020,"title":1021},"\u002Fcss-only-micro-interactions-animations\u002Fdialog-and-popover-animations\u002Fpopover-entry-and-exit-transitions","Popover Menus That Animate From Their Anchor",{"path":1023,"title":1024},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fchoosing-animation-durations","Choosing Animation Durations: How Long Motion Should Last",{"path":1026,"title":1027},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fcubic-bezier-overshoot-and-anticipation","Overshoot and Anticipation With cubic-bezier(): Motion With Character",{"path":1029,"title":1030},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design\u002Fentry-vs-exit-easing","Entry vs Exit Easing: Different Curves for Arriving and Leaving",{"path":1032,"title":1033},"\u002Fcss-only-micro-interactions-animations\u002Feasing-and-motion-design","Easing & Motion Design: Making CSS Motion Feel Intentional",{"path":1035,"title":1036},"\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":1038,"title":1039},"\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":1041,"title":1042},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":1044,"title":1045},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Fbutton-press-and-active-states","Button Press and  States",{"path":1047,"title":1048},"\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":1050,"title":1051},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":1053,"title":1054},"\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":1056,"title":1057},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":1059,"title":1060},"\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":1062,"title":1063},"\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":1065,"title":1066},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":1068,"title":1069},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fanimation-composition-and-stacking","Stacking Animations With animation-composition",{"path":1071,"title":1072},"\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":1074,"title":1075},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":1077,"title":1078},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":1080,"title":1081},"\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":1083,"title":1084},"\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":1086,"title":1087},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":1089,"title":1090},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fmulti-step-keyframes-and-per-keyframe-easing","Multi-Step Keyframes and Per-Keyframe Easing",{"path":1092,"title":1093},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":1095,"title":1096},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fanimating-box-shadow-and-filters-cheaply","Animating box-shadow and Filters Cheaply",{"path":1098,"title":1099},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcontain-property-for-animation-performance","The contain Property for Animation Performance",{"path":1101,"title":1102},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fcss-triggers-layout-paint-composite","Layout, Paint and Composite: What Triggers What",{"path":1104,"title":1105},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":1107,"title":1108},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":1110,"title":1111},"\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":1113,"title":1114},"\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":1116,"title":1117},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":1119,"title":1120},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":1122,"title":1123},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-parallax-effects","Scroll-Driven Parallax Effects in CSS",{"path":1125,"title":1126},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":1128,"title":1129},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":1131,"title":1132},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Ftimeline-scope-for-cross-element-animations","timeline-scope for Cross-Element Animations",{"path":1134,"title":1135},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fview-timeline-and-animation-range","View Timelines and animation-range",{"path":1137,"title":1138},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fcross-document-view-transitions","Cross-Document View Transitions",{"path":1140,"title":1141},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":1143,"title":1144},"\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":1146,"title":1147},"\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":1149,"title":1150},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-types-and-classes","View Transition Types and Classes",{"path":1152,"title":1153},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-for-list-reordering","View Transitions for List Reordering",{"path":1155,"title":1156},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":1158,"title":1159},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":1161,"title":1162},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":1164,"title":1165},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":1167,"title":1168},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-size-for-matching-widths","anchor-size(): Overlays That Match Their Trigger's Size",{"path":1170,"title":1171},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":1173,"title":1174},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":1176,"title":1177},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-light-dismiss-and-stacking","Popover Light Dismiss, Nesting and Stacking",{"path":1179,"title":1180},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fposition-area-grid-explained","position-area: The Anchor Placement Grid",{"path":1182,"title":1183},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fcontainer-query-polyfill-tradeoffs","Container Query Polyfills: What They Cost and When to Skip Them",{"path":1185,"title":1186},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":1188,"title":1189},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":1191,"title":1192},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":1194,"title":1195},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fintrinsic-layout-fallbacks-without-queries","Intrinsic Layout Fallbacks: Baselines That Adapt Without Any Query",{"path":1197,"title":1198},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ftesting-fallbacks-without-old-browsers","Testing CSS Fallbacks Without an Old Browser",{"path":1200,"title":1201},"\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":1203,"title":1204},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-query-range-and-logic-operators","Container Query Range Syntax and Logic Operators",{"path":1206,"title":1207},"\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":1209,"title":1210},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":1212,"title":1213},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":1215,"title":1216},"\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":1218,"title":1219},"\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":1221,"title":1222},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":1224,"title":1225},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":1227,"title":1228},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":1230,"title":1231},"\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":1233,"title":1234},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fgrid-auto-flow-dense-packing","grid-auto-flow: dense for Packed Layouts",{"path":1236,"title":1237},"\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":1239,"title":1240},"\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":1242,"title":1243},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":1245,"title":1246},"\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":1248,"title":1249},"\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":1251,"title":1252},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":1254,"title":1255},"\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":1257,"title":1258},"\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":1260,"title":1261},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-grow-and-flex-shrink-explained","flex-grow and flex-shrink Explained",{"path":1263,"title":1264},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflex-wrap-intrinsic-responsive-rows","Breakpoint-Free Responsive Rows With flex-wrap and flex-basis",{"path":1266,"title":1267},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns\u002Fflexbox-gap-and-spacing","Flexbox gap vs Margins: Spacing Items Without Edge Hacks",{"path":1269,"title":1270},"\u002Fmastering-container-queries-responsive-layouts\u002Fflexbox-layout-patterns","Flexbox Layout Patterns: One-Dimensional Layout for Real Components",{"path":1272,"title":1273},"\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":1275,"title":1276},"\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":1278,"title":1279},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Fdebugging-clamp-values","Debugging clamp(): Values That Are Ignored, Stuck or Never Fluid",{"path":1281,"title":1282},"\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":1284,"title":1285},"\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":1287,"title":1288},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":1290,"title":1291},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":1293,"title":1294},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":1296,"title":1297},"\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":1299,"title":1300},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":1302,"title":1303},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":1305,"title":1306},"\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":1308,"title":1309},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":1311,"title":1312},"\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":1314,"title":1315},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":1317,"title":1318},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fobject-fit-and-object-position","object-fit and object-position: Images That Fit Any Box",{"path":1320,"title":1321},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":1323,"title":1324},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":1326,"title":1327},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":1329,"title":1330},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcss-scope-for-component-styles","@scope for Component Styles: Short Selectors That Cannot Leak",{"path":1332,"title":1333},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":1335,"title":1336},"\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":1338,"title":1339},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fwriting-a-minimal-modern-reset","Writing a Minimal Modern CSS Reset: Every Line Justified",{"path":1341,"title":1342},"\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":1344,"title":1345},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has\u002Fempty-and-loading-states-with-has","Empty and Loading States With ()",{"path":1347,"title":1348},"\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":1350,"title":1351},"\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":1353,"title":1354},"\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":1356,"title":1357},"\u002Fmastering-container-queries-responsive-layouts\u002Fparent-aware-layouts-with-has","Parent-Aware Layouts With :has(): Letting Containers React to Their Contents",{"path":1359,"title":1360},"\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":1362,"title":1363},"\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":1365,"title":1366},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":1368,"title":1369},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":1371,"title":1372},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":1374,"title":1375},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":1377,"title":1378},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-hero-sections-with-container-queries","Responsive Hero Sections With Container Queries",{"path":1380,"title":1381},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":1383,"title":1384},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-pricing-tables","Responsive Pricing Tables: Aligned Features, a Clear Recommendation, Any Width",{"path":1386,"title":1387},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Ftabs-that-become-accordions","Tabs That Become an Accordion: One Component, Two Layouts",{"path":1389,"title":1390},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts\u002Fcss-only-carousel-with-scroll-snap","A CSS-Only Carousel With Scroll Snap",{"path":1392,"title":1393},"\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":1395,"title":1396},"\u002Fmastering-container-queries-responsive-layouts\u002Fscroll-snap-and-overflow-layouts","Scroll Snap & Overflow Layouts: Designing Components That Scroll on Purpose",{"path":1398,"title":1399},"\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":1401,"title":1402},"\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":1404,"title":1405},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fcombining-size-and-style-queries","Combining Size and Style Container Queries",{"path":1407,"title":1408},"\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":1410,"title":1411},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":1413,"title":1414},"\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":1416,"title":1417},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state\u002Fstyle-query-component-variants","Component Variants With Style Queries: One Token, Many Looks",{"path":1419,"title":1420},"\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":1422,"title":1423},"\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":1425,"title":1426},"\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":1428,"title":1429},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout","Viewport Units & Mobile Layout: Designing for the Screen You Actually Get",{"path":1431,"title":1432},"\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":1434,"title":1435},"\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":1437,"title":1438},"\u002Fmastering-container-queries-responsive-layouts\u002Fviewport-units-and-mobile-layout\u002Fvirtual-keyboard-and-interactive-widget","Layouts That Survive the Virtual Keyboard",{"title":1440,"caption":1441,"height":1442,"resizable":181,"html":1443,"css":1444},"A transition and a keyframe animation, interrupted","Hover a track, then leave before the box arrives. The transition turns around from where it is; the keyframe animation snaps straight back.",200,"\n\u003Cdiv class=\"stack\">\n  \u003Cdiv class=\"track\" tabindex=\"0\">\u003Cspan class=\"label\">transition\u003C\u002Fspan>\u003Cdiv class=\"box box--transition\">\u003C\u002Fdiv>\u003C\u002Fdiv>\n  \u003Cdiv class=\"track\" tabindex=\"0\">\u003Cspan class=\"label\">keyframes\u003C\u002Fspan>\u003Cdiv class=\"box box--keyframes\">\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003C\u002Fdiv>","\n.stack { display: grid; gap: 1rem; padding: 1rem; }\n.track { position: relative; padding: 0.75rem; border: 1px dashed var(--demo-border); border-radius: 10px; min-block-size: 3.5rem; }\n.track:focus-visible { outline: 2px solid var(--demo-accent); outline-offset: 2px; }\n.label { position: absolute; inset-block-start: 0.4rem; inset-inline-end: 0.6rem; font-size: 0.75rem; color: var(--demo-muted); }\n.box { inline-size: 2.5rem; block-size: 2.5rem; border-radius: 8px; background: var(--demo-accent); }\n.box--transition { transition: translate 600ms cubic-bezier(0.2, 0, 0, 1); }\n.track:hover .box--transition, .track:focus-within .box--transition { translate: 8rem 0; }\n.track:hover .box--keyframes, .track:focus-within .box--keyframes { animation: slide 600ms cubic-bezier(0.2, 0, 0, 1) forwards; }\n@keyframes slide { to { translate: 8rem 0; } }\n@media (prefers-reduced-motion: reduce) { .box--transition { transition-duration: 1ms; } .track:hover .box--keyframes, .track:focus-within .box--keyframes { animation-duration: 1ms; } }",1789717747708]