[{"data":1,"prerenderedAt":3068},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers":3,"content-all-pages":2805},{"id":4,"title":5,"body":6,"description":2785,"extension":2786,"meta":2787,"navigation":722,"path":2801,"seo":2802,"stem":2803,"__hash__":2804},"content\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Findex.md","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"type":7,"value":8,"toc":2765},"minimark",[9,13,37,44,50,73,76,81,84,135,137,141,144,153,159,165,171,178,283,285,289,303,308,327,341,354,372,374,378,560,573,575,579,584,591,915,1038,1041,1045,1049,1052,1118,1129,1133,1136,1380,1387,1391,1397,1421,1424,1428,1431,1452,1462,1472,1474,1478,1481,1792,2293,2307,2315,2317,2321,2327,2351,2357,2376,2378,2382,2385,2438,2440,2444,2522,2528,2547,2549,2553,2661,2663,2667,2683,2689,2698,2704,2713,2715,2719,2761],[10,11,5],"h1",{"id":12},"view-transitions-for-css-developers-the-pseudo-element-tree-snapshots-and-named-elements",[14,15,16,17,21,22,26,27,30,31,36],"p",{},"Most CSS animation work is about persuading a single element to move between two states you control. The View Transitions API inverts that: it lets the browser animate between two ",[18,19,20],"em",{},"renderings of the whole page",", including elements that were destroyed and elements that did not exist a moment ago. That is something no amount of ",[23,24,25],"code",{},"transition"," or ",[23,28,29],{},"@keyframes"," could ever express, because both of those need a live element that persists across the change. This guide sits inside ",[32,33,35],"a",{"href":34},"\u002Fcss-only-micro-interactions-animations\u002F","CSS-Only Micro-Interactions & Animations"," and approaches the feature the way a CSS author meets it in practice: as a generated tree of pseudo-elements you style, with a very small JavaScript or at-rule trigger attached to the front.",[14,38,39,40,43],{},"The mental shift is worth stating up front. You are not animating your DOM. You are animating pictures of it. Once that clicks, every strange behaviour of the API — why named elements must be unique, why text reflow looks like a squash, why ",[23,41,42],{},"position: fixed"," elements jump — stops being strange and becomes a direct consequence of the model.",[14,45,46],{},[47,48,49],"strong",{},"What this guide covers:",[51,52,53,57,60,66],"ul",{},[54,55,56],"li",{},"The capture-mutate-capture-animate lifecycle and what a \"snapshot\" really is",[54,58,59],{},"The four pseudo-elements the browser generates, and which one you should target for what",[54,61,62,65],{},[23,63,64],{},"view-transition-name"," as the mechanism that splits the page into independently animated groups",[54,67,68,69,72],{},"The ",[23,70,71],{},"@view-transition { navigation: auto }"," rule that extends all of this across page loads",[74,75],"hr",{},[77,78,80],"h2",{"id":79},"prerequisites","Prerequisites",[14,82,83],{},"Before working through this guide you should be comfortable with:",[51,85,86,108,115,122,128],{},[54,87,88,89,91,92,95,96,99,100,103,104,107],{},"Writing ",[23,90,29],{}," and applying them with the ",[23,93,94],{},"animation"," shorthand, including ",[23,97,98],{},"animation-duration",", ",[23,101,102],{},"animation-timing-function",", and ",[23,105,106],{},"animation-fill-mode",".",[54,109,110,111,114],{},"CSS pseudo-elements and how a selector like ",[23,112,113],{},"::before"," targets something with no markup of its own.",[54,116,117,118,121],{},"Stacking contexts and ",[23,119,120],{},"z-index",", since the transition overlay creates its own.",[54,123,124,127],{},[23,125,126],{},"prefers-reduced-motion"," and why motion needs a user-preference escape hatch.",[54,129,130,131,107],{},"The difference between state-driven and time-driven animation, covered in ",[32,132,134],{"href":133},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002F","CSS Transition Fundamentals",[74,136],{},[77,138,140],{"id":139},"the-core-mechanism-capture-mutate-capture-animate","The core mechanism: capture, mutate, capture, animate",[14,142,143],{},"A view transition is a four-phase operation the browser runs on your behalf.",[14,145,146,149,150,152],{},[47,147,148],{},"Phase one — capture the old state."," The browser paints the current document and stores the result. Elements carrying a ",[23,151,64],{}," are captured individually; everything else is flattened together into one image called the root snapshot. Alongside each image the browser records geometry: the element's border-box size, its position in the viewport, and its transform.",[14,154,155,158],{},[47,156,157],{},"Phase two — apply your DOM change."," Rendering is suspended while this happens. You swap classes, replace innerHTML, navigate, sort a list — whatever the change is. Because rendering is paused, the user never sees the intermediate frame where old content has gone and new content has not painted. This alone eliminates an entire family of flicker bugs.",[14,160,161,164],{},[47,162,163],{},"Phase three — capture the new state."," The browser repeats phase one against the mutated document, producing a second set of images and a second set of geometry records.",[14,166,167,170],{},[47,168,169],{},"Phase four — build the overlay and animate."," The browser constructs a tree of pseudo-elements above everything else on the page, populates it with the two sets of captures, applies default animations, and runs them. When the animations finish, the tree is torn down and the real, live, interactive DOM is revealed underneath.",[14,172,173,174,177],{},"The critical consequence of phase four is that during the animation the user is looking at ",[47,175,176],{},"static images",", not working UI. Text inside a snapshot cannot be selected. Buttons cannot be clicked. Video is frozen on a frame. This is why transitions should be short — the platform default of 250ms is a deliberate choice, not an arbitrary one — and why a two-second cinematic page morph is a usability regression dressed as polish.",[179,180,186,187,186,191,186,195,186,202,186,213,186,218,186,224,186,229,186,233,186,236,186,241,186,245,186,250,186,253,186,260,186,264,186,268,186,271,186,275,186,278],"svg",{"viewBox":181,"role":182,"ariaLabel":183,"xmlns":184,"style":185},"0 0 720 400","img","The pseudo-element tree a view transition generates, from the root down to the old and new snapshots","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[188,189,190],"title",{},"The view transition pseudo-element tree",[192,193,194],"desc",{},"A four-level tree: the root overlay contains a group per name, each group contains an image pair, and each pair contains an old and a new snapshot.",[196,197,201],"text",{"x":198,"y":199,"style":200},"360","26","text-anchor:middle;fill:currentColor;font:700 18px sans-serif","Generated overlay tree (one branch per name)",[203,204],"rect",{"x":205,"y":206,"width":205,"height":207,"rx":208,"fill":209,"opacity":210,"stroke":211,"strokeWidth":212},"240","50","44","8","#7aa2ff","0.30","currentColor","1.5",[196,214,217],{"x":198,"y":215,"style":216},"78","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","::view-transition",[219,220],"line",{"x1":198,"y1":221,"x2":198,"y2":222,"stroke":211,"strokeWidth":212,"opacity":223},"94","130","0.6",[203,225],{"x":226,"y":222,"width":227,"height":207,"rx":208,"fill":209,"opacity":228,"stroke":211,"strokeWidth":212},"210","300","0.22",[196,230,232],{"x":198,"y":231,"style":216},"158","::view-transition-group(root)",[219,234],{"x1":198,"y1":235,"x2":198,"y2":226,"stroke":211,"strokeWidth":212,"opacity":223},"174",[203,237],{"x":238,"y":226,"width":239,"height":207,"rx":208,"fill":209,"opacity":240,"stroke":211,"strokeWidth":212},"192","336","0.15",[196,242,244],{"x":198,"y":243,"style":216},"238","::view-transition-image-pair(root)",[246,247],"path",{"d":248,"fill":249,"stroke":211,"strokeWidth":212,"opacity":223},"M360 254 L360 274 L210 274 L210 292","none",[246,251],{"d":252,"fill":249,"stroke":211,"strokeWidth":212,"opacity":223},"M360 254 L360 274 L510 274 L510 292",[203,254],{"x":255,"y":256,"width":257,"height":258,"rx":208,"fill":249,"stroke":211,"strokeWidth":212,"opacity":259},"96","292","228","56","0.7",[196,261,263],{"x":226,"y":262,"style":216},"316","-old(root)",[196,265,267],{"x":226,"y":239,"style":266},"text-anchor:middle;fill:currentColor;font:11px sans-serif;opacity:0.75","image of the before state",[203,269],{"x":270,"y":256,"width":257,"height":258,"rx":208,"fill":249,"stroke":211,"strokeWidth":212,"opacity":259},"396",[196,272,274],{"x":273,"y":262,"style":216},"510","-new(root)",[196,276,277],{"x":273,"y":239,"style":266},"image of the after state",[196,279,282],{"x":198,"y":280,"style":281},"378","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.7","Every named element gets its own group \u002F pair \u002F old \u002F new branch.",[74,284],{},[77,286,288],{"id":287},"the-four-pseudo-elements-and-what-each-is-for","The four pseudo-elements and what each is for",[14,290,291,292,294,295,298,299,302],{},"The overlay tree is generated on the document root, so all four selectors are written unattached — ",[23,293,217],{},", not ",[23,296,297],{},"html::view-transition",". Each of the lower three takes a name argument, and ",[23,300,301],{},"*"," matches all of them.",[14,304,305,307],{},[23,306,217],{}," is the overlay container. It sits above every stacking context on the page and covers the viewport. Style it when you need something behind or across the whole transition: a background colour that shows through while both snapshots are partly transparent, or an opacity ceiling on the entire effect.",[14,309,310,313,314,99,317,103,320,323,324,326],{},[23,311,312],{},"::view-transition-group(name)"," is the positioned box for one captured element. This is the pseudo-element that carries the geometry: the browser gives it an animation interpolating ",[23,315,316],{},"width",[23,318,319],{},"height",[23,321,322],{},"transform"," from the old measurements to the new ones. If a thing moves or resizes during a transition, the group is what moves and resizes. It is also where you set ",[23,325,98],{}," when you want to retime a morph.",[14,328,329,332,333,336,337,340],{},[23,330,331],{},"::view-transition-image-pair(name)"," is a wrapper with ",[23,334,335],{},"isolation: isolate"," around the two snapshots. You rarely target it directly. Its one real job is establishing an isolated blending context so the old and new images can composite against each other with ",[23,338,339],{},"mix-blend-mode"," rather than against the page behind them.",[14,342,343,346,347,350,351,353],{},[23,344,345],{},"::view-transition-old(name)"," and ",[23,348,349],{},"::view-transition-new(name)"," are the two snapshots — replaced elements whose content is the captured image. These are the ones you attach custom ",[23,352,29],{}," to when you want something other than a fade. They both live inside the pair, absolutely positioned, so they overlap by default.",[14,355,356,357,346,360,363,364,367,368,371],{},"Because they are replaced elements, ",[23,358,359],{},"object-fit",[23,361,362],{},"object-position"," apply to them, which matters whenever the old and new captures have different aspect ratios. The default ",[23,365,366],{},"object-fit: fill"," is what produces the familiar \"text squashes as the box grows\" artifact on a shared-element morph; switching to ",[23,369,370],{},"object-fit: cover"," on both snapshots usually reads better.",[74,373],{},[77,375,377],{"id":376},"syntax-and-parameters","Syntax and parameters",[379,380,381,397],"table",{},[382,383,384],"thead",{},[385,386,387,391,394],"tr",{},[388,389,390],"th",{},"Token",[388,392,393],{},"Accepted values",[388,395,396],{},"Default",[398,399,400,419,435,454,472,491,511,525,539],"tbody",{},[385,401,402,407,415],{},[403,404,405],"td",{},[23,406,64],{},[403,408,409,411,412],{},[23,410,249],{},", a custom ident, or ",[23,413,414],{},"match-element",[403,416,417],{},[23,418,249],{},[385,420,421,426,431],{},[403,422,423],{},[23,424,425],{},"view-transition-class",[403,427,428,430],{},[23,429,249],{}," or one or more custom idents",[403,432,433],{},[23,434,249],{},[385,436,437,442,449],{},[403,438,439],{},[23,440,441],{},"@view-transition { navigation: … }",[403,443,444,99,447],{},[23,445,446],{},"auto",[23,448,249],{},[403,450,451,453],{},[23,452,249],{}," (no rule = no cross-document transition)",[385,455,456,461,469],{},[403,457,458],{},[23,459,460],{},"::view-transition-group(x)",[403,462,463,466,467],{},[23,464,465],{},"x"," = a name, or ",[23,468,301],{},[403,470,471],{},"—",[385,473,474,483,489],{},[403,475,476,479,480],{},[23,477,478],{},"::view-transition-old(x)"," \u002F ",[23,481,482],{},"-new(x)",[403,484,485,466,487],{},[23,486,465],{},[23,488,301],{},[403,490,471],{},[385,492,493,496,505],{},[403,494,495],{},"Default group animation",[403,497,498,499,99,501,99,503],{},"interpolates ",[23,500,316],{},[23,502,319],{},[23,504,322],{},[403,506,507,508],{},"250ms ",[23,509,510],{},"ease",[385,512,513,516,521],{},[403,514,515],{},"Default old snapshot animation",[403,517,518],{},[23,519,520],{},"opacity: 1 → 0",[403,522,507,523],{},[23,524,510],{},[385,526,527,530,535],{},[403,528,529],{},"Default new snapshot animation",[403,531,532],{},[23,533,534],{},"opacity: 0 → 1",[403,536,507,537],{},[23,538,510],{},[385,540,541,546,556],{},[403,542,543,545],{},[23,544,64],{}," on root",[403,547,548,549,552,553],{},"implicit name ",[23,550,551],{},"root"," on ",[23,554,555],{},":root",[403,557,558],{},[23,559,551],{},[14,561,562,563,565,566,569,570,572],{},"Two entries deserve a note. ",[23,564,425],{}," is the escape hatch for styling many names at once: give twelve cards the same class and you can retime all twelve groups with a single ",[23,567,568],{},"::view-transition-group(.card)"," rule instead of twelve selectors. And ",[23,571,414],{}," is a newer value that asks the engine to derive a stable identity per element rather than making you invent unique idents — useful, but its availability is narrower than the rest of the API, so verify before relying on it.",[74,574],{},[77,576,578],{"id":577},"step-by-step-from-no-css-to-a-controlled-transition","Step by step: from no CSS to a controlled transition",[580,581,583],"h3",{"id":582},"step-1-trigger-a-transition-and-take-the-default","Step 1 — trigger a transition and take the default",[14,585,586,587,590],{},"The entry point for a transition inside a single document is ",[23,588,589],{},"document.startViewTransition()",", which takes a callback that performs the DOM change. This is the one piece that is not CSS, and it is deliberately tiny.",[592,593,598],"pre",{"className":594,"code":595,"language":596,"meta":597,"style":597},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003Cbutton id=\"toggle\" type=\"button\">Switch view\u003C\u002Fbutton>\n\u003Cmain id=\"panel\" class=\"grid\">\n  \u003Carticle class=\"item\">Alpha\u003C\u002Farticle>\n  \u003Carticle class=\"item\">Beta\u003C\u002Farticle>\n\u003C\u002Fmain>\n\n\u003Cscript>\n  const btn = document.getElementById('toggle');\n  const panel = document.getElementById('panel');\n\n  btn.addEventListener('click', () => {\n    \u002F\u002F Guard so unsupported browsers still get the state change, just with no animation.\n    if (!document.startViewTransition) {\n      panel.classList.toggle('list');\n      return;\n    }\n    document.startViewTransition(() => {\n      panel.classList.toggle('list');\n    });\n  });\n\u003C\u002Fscript>\n","html","",[23,599,600,639,664,687,707,717,724,734,763,784,789,812,819,834,850,859,865,881,894,900,906],{"__ignoreMap":597},[601,602,604,608,612,616,619,623,626,628,631,634,636],"span",{"class":219,"line":603},1,[601,605,607],{"class":606},"suds8","\u003C",[601,609,611],{"class":610},"sne4z","button",[601,613,615],{"class":614},"s-5SL"," id",[601,617,618],{"class":606},"=",[601,620,622],{"class":621},"sT6z2","\"toggle\"",[601,624,625],{"class":614}," type",[601,627,618],{"class":606},[601,629,630],{"class":621},"\"button\"",[601,632,633],{"class":606},">Switch view\u003C\u002F",[601,635,611],{"class":610},[601,637,638],{"class":606},">\n",[601,640,642,644,647,649,651,654,657,659,662],{"class":219,"line":641},2,[601,643,607],{"class":606},[601,645,646],{"class":610},"main",[601,648,615],{"class":614},[601,650,618],{"class":606},[601,652,653],{"class":621},"\"panel\"",[601,655,656],{"class":614}," class",[601,658,618],{"class":606},[601,660,661],{"class":621},"\"grid\"",[601,663,638],{"class":606},[601,665,667,670,673,675,677,680,683,685],{"class":219,"line":666},3,[601,668,669],{"class":606},"  \u003C",[601,671,672],{"class":610},"article",[601,674,656],{"class":614},[601,676,618],{"class":606},[601,678,679],{"class":621},"\"item\"",[601,681,682],{"class":606},">Alpha\u003C\u002F",[601,684,672],{"class":610},[601,686,638],{"class":606},[601,688,690,692,694,696,698,700,703,705],{"class":219,"line":689},4,[601,691,669],{"class":606},[601,693,672],{"class":610},[601,695,656],{"class":614},[601,697,618],{"class":606},[601,699,679],{"class":621},[601,701,702],{"class":606},">Beta\u003C\u002F",[601,704,672],{"class":610},[601,706,638],{"class":606},[601,708,710,713,715],{"class":219,"line":709},5,[601,711,712],{"class":606},"\u003C\u002F",[601,714,646],{"class":610},[601,716,638],{"class":606},[601,718,720],{"class":219,"line":719},6,[601,721,723],{"emptyLinePlaceholder":722},true,"\n",[601,725,727,729,732],{"class":219,"line":726},7,[601,728,607],{"class":606},[601,730,731],{"class":610},"script",[601,733,638],{"class":606},[601,735,737,741,744,747,750,754,757,760],{"class":219,"line":736},8,[601,738,740],{"class":739},"sHUrx","  const",[601,742,743],{"class":614}," btn",[601,745,746],{"class":739}," =",[601,748,749],{"class":606}," document.",[601,751,753],{"class":752},"sKwhi","getElementById",[601,755,756],{"class":606},"(",[601,758,759],{"class":621},"'toggle'",[601,761,762],{"class":606},");\n",[601,764,766,768,771,773,775,777,779,782],{"class":219,"line":765},9,[601,767,740],{"class":739},[601,769,770],{"class":614}," panel",[601,772,746],{"class":739},[601,774,749],{"class":606},[601,776,753],{"class":752},[601,778,756],{"class":606},[601,780,781],{"class":621},"'panel'",[601,783,762],{"class":606},[601,785,787],{"class":219,"line":786},10,[601,788,723],{"emptyLinePlaceholder":722},[601,790,792,795,798,800,803,806,809],{"class":219,"line":791},11,[601,793,794],{"class":606},"  btn.",[601,796,797],{"class":752},"addEventListener",[601,799,756],{"class":606},[601,801,802],{"class":621},"'click'",[601,804,805],{"class":606},", () ",[601,807,808],{"class":739},"=>",[601,810,811],{"class":606}," {\n",[601,813,815],{"class":219,"line":814},12,[601,816,818],{"class":817},"sLBg1","    \u002F\u002F Guard so unsupported browsers still get the state change, just with no animation.\n",[601,820,822,825,828,831],{"class":219,"line":821},13,[601,823,824],{"class":739},"    if",[601,826,827],{"class":606}," (",[601,829,830],{"class":739},"!",[601,832,833],{"class":606},"document.startViewTransition) {\n",[601,835,837,840,843,845,848],{"class":219,"line":836},14,[601,838,839],{"class":606},"      panel.classList.",[601,841,842],{"class":752},"toggle",[601,844,756],{"class":606},[601,846,847],{"class":621},"'list'",[601,849,762],{"class":606},[601,851,853,856],{"class":219,"line":852},15,[601,854,855],{"class":739},"      return",[601,857,858],{"class":606},";\n",[601,860,862],{"class":219,"line":861},16,[601,863,864],{"class":606},"    }\n",[601,866,868,871,874,877,879],{"class":219,"line":867},17,[601,869,870],{"class":606},"    document.",[601,872,873],{"class":752},"startViewTransition",[601,875,876],{"class":606},"(() ",[601,878,808],{"class":739},[601,880,811],{"class":606},[601,882,884,886,888,890,892],{"class":219,"line":883},18,[601,885,839],{"class":606},[601,887,842],{"class":752},[601,889,756],{"class":606},[601,891,847],{"class":621},[601,893,762],{"class":606},[601,895,897],{"class":219,"line":896},19,[601,898,899],{"class":606},"    });\n",[601,901,903],{"class":219,"line":902},20,[601,904,905],{"class":606},"  });\n",[601,907,909,911,913],{"class":219,"line":908},21,[601,910,712],{"class":606},[601,912,731],{"class":610},[601,914,638],{"class":606},[592,916,920],{"className":917,"code":918,"language":919,"meta":597,"style":597},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast",".grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }\n.grid.list { grid-template-columns: 1fr; }\n.item { padding: 1rem; border: 1px solid currentColor; border-radius: 10px; }\n","css",[23,921,922,973,990],{"__ignoreMap":597},[601,923,924,927,930,933,936,939,942,945,947,950,953,956,958,960,963,965,967,970],{"class":219,"line":603},[601,925,926],{"class":614},".grid",[601,928,929],{"class":606}," { ",[601,931,932],{"class":614},"display",[601,934,935],{"class":606},": ",[601,937,938],{"class":614},"grid",[601,940,941],{"class":606},"; ",[601,943,944],{"class":614},"grid-template-columns",[601,946,935],{"class":606},[601,948,949],{"class":614},"1",[601,951,952],{"class":739},"fr",[601,954,955],{"class":614}," 1",[601,957,952],{"class":739},[601,959,941],{"class":606},[601,961,962],{"class":614},"gap",[601,964,935],{"class":606},[601,966,949],{"class":614},[601,968,969],{"class":739},"rem",[601,971,972],{"class":606},"; }\n",[601,974,975,978,980,982,984,986,988],{"class":219,"line":641},[601,976,977],{"class":614},".grid.list",[601,979,929],{"class":606},[601,981,944],{"class":614},[601,983,935],{"class":606},[601,985,949],{"class":614},[601,987,952],{"class":739},[601,989,972],{"class":606},[601,991,992,995,997,1000,1002,1004,1006,1008,1011,1013,1015,1018,1021,1024,1026,1029,1031,1034,1036],{"class":219,"line":666},[601,993,994],{"class":614},".item",[601,996,929],{"class":606},[601,998,999],{"class":614},"padding",[601,1001,935],{"class":606},[601,1003,949],{"class":614},[601,1005,969],{"class":739},[601,1007,941],{"class":606},[601,1009,1010],{"class":614},"border",[601,1012,935],{"class":606},[601,1014,949],{"class":614},[601,1016,1017],{"class":739},"px",[601,1019,1020],{"class":614}," solid",[601,1022,1023],{"class":614}," currentColor",[601,1025,941],{"class":606},[601,1027,1028],{"class":614},"border-radius",[601,1030,935],{"class":606},[601,1032,1033],{"class":614},"10",[601,1035,1017],{"class":739},[601,1037,972],{"class":606},[14,1039,1040],{},"With no view-transition CSS at all, this already animates: the browser cross-fades the whole page between the two-column and one-column renderings. The demo below plays the exact opacity curves that default produces.",[1042,1043],"live-demo",{"name":1044},"vt-default-crossfade",[580,1046,1048],{"id":1047},"step-2-retime-the-default-cross-fade","Step 2 — retime the default cross-fade",[14,1050,1051],{},"The default animations are ordinary CSS animations on ordinary pseudo-elements, so overriding their duration is just a declaration.",[592,1053,1055],{"className":917,"code":1054,"language":919,"meta":597,"style":597},"::view-transition-old(root),\n::view-transition-new(root) {\n  animation-duration: 400ms;\n  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n}\n",[23,1056,1057,1062,1067,1082,1113],{"__ignoreMap":597},[601,1058,1059],{"class":219,"line":603},[601,1060,1061],{"class":606},"::view-transition-old(root),\n",[601,1063,1064],{"class":219,"line":641},[601,1065,1066],{"class":606},"::view-transition-new(root) {\n",[601,1068,1069,1072,1074,1077,1080],{"class":219,"line":666},[601,1070,1071],{"class":614},"  animation-duration",[601,1073,935],{"class":606},[601,1075,1076],{"class":614},"400",[601,1078,1079],{"class":739},"ms",[601,1081,858],{"class":606},[601,1083,1084,1087,1089,1092,1094,1097,1099,1102,1104,1107,1109,1111],{"class":219,"line":689},[601,1085,1086],{"class":614},"  animation-timing-function",[601,1088,935],{"class":606},[601,1090,1091],{"class":614},"cubic-bezier",[601,1093,756],{"class":606},[601,1095,1096],{"class":614},"0.4",[601,1098,99],{"class":606},[601,1100,1101],{"class":614},"0",[601,1103,99],{"class":606},[601,1105,1106],{"class":614},"0.2",[601,1108,99],{"class":606},[601,1110,949],{"class":614},[601,1112,762],{"class":606},[601,1114,1115],{"class":219,"line":709},[601,1116,1117],{"class":606},"}\n",[14,1119,1120,1121,1124,1125,1128],{},"Note that you are ",[18,1122,1123],{},"not"," re-declaring ",[23,1126,1127],{},"animation-name",". Leaving the user-agent keyframes in place and adjusting only duration and easing is the lightest possible intervention, and it is often all a project needs.",[580,1130,1132],{"id":1131},"step-3-replace-the-animation-entirely","Step 3 — replace the animation entirely",[14,1134,1135],{},"Declare your own keyframes and assign them to the two snapshots. Because both snapshots are stacked in the same pair, the old one should generally be pushed out of the way as the new one arrives.",[592,1137,1139],{"className":917,"code":1138,"language":919,"meta":597,"style":597},"@keyframes vt-slide-out-left {\n  from { opacity: 1; transform: translateX(0); }\n  to   { opacity: 0; transform: translateX(-30%); }\n}\n@keyframes vt-slide-in-right {\n  from { opacity: 0; transform: translateX(30%); }\n  to   { opacity: 1; transform: translateX(0); }\n}\n\n::view-transition-old(root) {\n  animation: vt-slide-out-left 300ms cubic-bezier(0.4, 0, 0.2, 1) both;\n}\n::view-transition-new(root) {\n  animation: vt-slide-in-right 300ms cubic-bezier(0.4, 0, 0.2, 1) both;\n}\n",[23,1140,1141,1151,1181,1213,1217,1226,1255,1281,1285,1289,1294,1333,1337,1341,1376],{"__ignoreMap":597},[601,1142,1143,1145,1149],{"class":219,"line":603},[601,1144,29],{"class":739},[601,1146,1148],{"class":1147},"soyes"," vt-slide-out-left",[601,1150,811],{"class":606},[601,1152,1153,1156,1158,1161,1163,1165,1167,1169,1171,1174,1176,1178],{"class":219,"line":641},[601,1154,1155],{"class":614},"  from",[601,1157,929],{"class":606},[601,1159,1160],{"class":614},"opacity",[601,1162,935],{"class":606},[601,1164,949],{"class":614},[601,1166,941],{"class":606},[601,1168,322],{"class":614},[601,1170,935],{"class":606},[601,1172,1173],{"class":614},"translateX",[601,1175,756],{"class":606},[601,1177,1101],{"class":614},[601,1179,1180],{"class":606},"); }\n",[601,1182,1183,1186,1189,1191,1193,1195,1197,1199,1201,1203,1205,1208,1211],{"class":219,"line":666},[601,1184,1185],{"class":614},"  to",[601,1187,1188],{"class":606},"   { ",[601,1190,1160],{"class":614},[601,1192,935],{"class":606},[601,1194,1101],{"class":614},[601,1196,941],{"class":606},[601,1198,322],{"class":614},[601,1200,935],{"class":606},[601,1202,1173],{"class":614},[601,1204,756],{"class":606},[601,1206,1207],{"class":614},"-30",[601,1209,1210],{"class":739},"%",[601,1212,1180],{"class":606},[601,1214,1215],{"class":219,"line":689},[601,1216,1117],{"class":606},[601,1218,1219,1221,1224],{"class":219,"line":709},[601,1220,29],{"class":739},[601,1222,1223],{"class":1147}," vt-slide-in-right",[601,1225,811],{"class":606},[601,1227,1228,1230,1232,1234,1236,1238,1240,1242,1244,1246,1248,1251,1253],{"class":219,"line":719},[601,1229,1155],{"class":614},[601,1231,929],{"class":606},[601,1233,1160],{"class":614},[601,1235,935],{"class":606},[601,1237,1101],{"class":614},[601,1239,941],{"class":606},[601,1241,322],{"class":614},[601,1243,935],{"class":606},[601,1245,1173],{"class":614},[601,1247,756],{"class":606},[601,1249,1250],{"class":614},"30",[601,1252,1210],{"class":739},[601,1254,1180],{"class":606},[601,1256,1257,1259,1261,1263,1265,1267,1269,1271,1273,1275,1277,1279],{"class":219,"line":726},[601,1258,1185],{"class":614},[601,1260,1188],{"class":606},[601,1262,1160],{"class":614},[601,1264,935],{"class":606},[601,1266,949],{"class":614},[601,1268,941],{"class":606},[601,1270,322],{"class":614},[601,1272,935],{"class":606},[601,1274,1173],{"class":614},[601,1276,756],{"class":606},[601,1278,1101],{"class":614},[601,1280,1180],{"class":606},[601,1282,1283],{"class":219,"line":736},[601,1284,1117],{"class":606},[601,1286,1287],{"class":219,"line":765},[601,1288,723],{"emptyLinePlaceholder":722},[601,1290,1291],{"class":219,"line":786},[601,1292,1293],{"class":606},"::view-transition-old(root) {\n",[601,1295,1296,1299,1302,1304,1306,1309,1311,1313,1315,1317,1319,1321,1323,1325,1328,1331],{"class":219,"line":791},[601,1297,1298],{"class":614},"  animation",[601,1300,1301],{"class":606},": vt-slide-out-left ",[601,1303,227],{"class":614},[601,1305,1079],{"class":739},[601,1307,1308],{"class":614}," cubic-bezier",[601,1310,756],{"class":606},[601,1312,1096],{"class":614},[601,1314,99],{"class":606},[601,1316,1101],{"class":614},[601,1318,99],{"class":606},[601,1320,1106],{"class":614},[601,1322,99],{"class":606},[601,1324,949],{"class":614},[601,1326,1327],{"class":606},") ",[601,1329,1330],{"class":614},"both",[601,1332,858],{"class":606},[601,1334,1335],{"class":219,"line":814},[601,1336,1117],{"class":606},[601,1338,1339],{"class":219,"line":821},[601,1340,1066],{"class":606},[601,1342,1343,1345,1348,1350,1352,1354,1356,1358,1360,1362,1364,1366,1368,1370,1372,1374],{"class":219,"line":836},[601,1344,1298],{"class":614},[601,1346,1347],{"class":606},": vt-slide-in-right ",[601,1349,227],{"class":614},[601,1351,1079],{"class":739},[601,1353,1308],{"class":614},[601,1355,756],{"class":606},[601,1357,1096],{"class":614},[601,1359,99],{"class":606},[601,1361,1101],{"class":614},[601,1363,99],{"class":606},[601,1365,1106],{"class":614},[601,1367,99],{"class":606},[601,1369,949],{"class":614},[601,1371,1327],{"class":606},[601,1373,1330],{"class":614},[601,1375,858],{"class":606},[601,1377,1378],{"class":219,"line":852},[601,1379,1117],{"class":606},[14,1381,1382,1383,107],{},"The step-by-step mechanics of writing these overrides, including what happens when the two durations disagree, are worked through on ",[32,1384,1386],{"href":1385},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fsame-document-view-transitions\u002F","same-document view transitions",[580,1388,1390],{"id":1389},"step-4-name-an-element-so-it-animates-on-its-own","Step 4 — name an element so it animates on its own",[14,1392,1393,1394,1396],{},"So far the entire page has been one snapshot. Assigning ",[23,1395,64],{}," to an element lifts it out of the root capture and gives it its own group, image pair, and snapshot pair.",[592,1398,1400],{"className":917,"code":1399,"language":919,"meta":597,"style":597},".item--featured {\n  view-transition-name: featured-card;\n}\n",[23,1401,1402,1409,1417],{"__ignoreMap":597},[601,1403,1404,1407],{"class":219,"line":603},[601,1405,1406],{"class":614},".item--featured",[601,1408,811],{"class":606},[601,1410,1411,1414],{"class":219,"line":641},[601,1412,1413],{"class":614},"  view-transition-name",[601,1415,1416],{"class":606},": featured-card;\n",[601,1418,1419],{"class":219,"line":666},[601,1420,1117],{"class":606},[14,1422,1423],{},"That single declaration is enough for the browser to measure the element before and after, and to generate a group animation interpolating position and size between the two measurements. If the element occupies a different rectangle on either side of the DOM change, it appears to travel and grow.",[580,1425,1427],{"id":1426},"step-5-extend-the-transition-across-a-page-load","Step 5 — extend the transition across a page load",[14,1429,1430],{},"Everything above happens inside one document. To make a transition survive a navigation between two same-origin pages, both documents opt in with an at-rule:",[592,1432,1434],{"className":917,"code":1433,"language":919,"meta":597,"style":597},"@view-transition {\n  navigation: auto;\n}\n",[23,1435,1436,1443,1448],{"__ignoreMap":597},[601,1437,1438,1441],{"class":219,"line":603},[601,1439,1440],{"class":739},"@view-transition",[601,1442,811],{"class":606},[601,1444,1445],{"class":219,"line":641},[601,1446,1447],{"class":606},"  navigation: auto;\n",[601,1449,1450],{"class":219,"line":666},[601,1451,1117],{"class":606},[14,1453,1454,1455,1458,1459,1461],{},"Put that in the stylesheet of the outgoing page and the incoming page. When the user follows a same-origin link, the browser captures the old document, waits for the new one, captures it, and runs the same pseudo-element machinery across the boundary. Names match across documents, so an element named ",[23,1456,1457],{},"hero-image"," on a list page and an element named ",[23,1460,1457],{}," on a detail page will morph into each other with no script at all.",[14,1463,68,1464,1467,1468,1471],{},[23,1465,1466],{},"navigation: auto"," value means \"transition on navigations the browser considers appropriate\" — which excludes cross-origin navigations, and excludes reloads. ",[23,1469,1470],{},"navigation: none"," explicitly opts out, useful for overriding a site-wide rule on a particular page.",[74,1473],{},[77,1475,1477],{"id":1476},"an-annotated-production-example-a-filterable-card-list","An annotated production example: a filterable card list",[14,1479,1480],{},"This is a realistic component: a card grid where activating a filter changes which cards are visible. Each card is named so it slides to its new slot rather than the whole grid cross-fading.",[592,1482,1484],{"className":594,"code":1483,"language":596,"meta":597,"style":597},"\u003Cdiv class=\"toolbar\">\n  \u003Cbutton type=\"button\" data-filter=\"all\" class=\"chip\">All\u003C\u002Fbutton>\n  \u003Cbutton type=\"button\" data-filter=\"design\" class=\"chip\">Design\u003C\u002Fbutton>\n\u003C\u002Fdiv>\n\n\u003Cul class=\"cards\">\n  \u003Cli class=\"card\" data-tag=\"design\" style=\"view-transition-name: card-1\">\n    \u003Ch3>Colour systems\u003C\u002Fh3>\n    \u003Cp>Token naming for themeable palettes.\u003C\u002Fp>\n  \u003C\u002Fli>\n  \u003Cli class=\"card\" data-tag=\"code\" style=\"view-transition-name: card-2\">\n    \u003Ch3>Layout primitives\u003C\u002Fh3>\n    \u003Cp>Composable spacing and alignment.\u003C\u002Fp>\n  \u003C\u002Fli>\n  \u003Cli class=\"card\" data-tag=\"design\" style=\"view-transition-name: card-3\">\n    \u003Ch3>Motion tokens\u003C\u002Fh3>\n    \u003Cp>Durations and easing as custom properties.\u003C\u002Fp>\n  \u003C\u002Fli>\n\u003C\u002Ful>\n",[23,1485,1486,1502,1536,1568,1576,1580,1595,1625,1639,1652,1661,1689,1702,1715,1723,1750,1763,1776,1784],{"__ignoreMap":597},[601,1487,1488,1490,1493,1495,1497,1500],{"class":219,"line":603},[601,1489,607],{"class":606},[601,1491,1492],{"class":610},"div",[601,1494,656],{"class":614},[601,1496,618],{"class":606},[601,1498,1499],{"class":621},"\"toolbar\"",[601,1501,638],{"class":606},[601,1503,1504,1506,1508,1510,1512,1514,1517,1519,1522,1524,1526,1529,1532,1534],{"class":219,"line":641},[601,1505,669],{"class":606},[601,1507,611],{"class":610},[601,1509,625],{"class":614},[601,1511,618],{"class":606},[601,1513,630],{"class":621},[601,1515,1516],{"class":614}," data-filter",[601,1518,618],{"class":606},[601,1520,1521],{"class":621},"\"all\"",[601,1523,656],{"class":614},[601,1525,618],{"class":606},[601,1527,1528],{"class":621},"\"chip\"",[601,1530,1531],{"class":606},">All\u003C\u002F",[601,1533,611],{"class":610},[601,1535,638],{"class":606},[601,1537,1538,1540,1542,1544,1546,1548,1550,1552,1555,1557,1559,1561,1564,1566],{"class":219,"line":666},[601,1539,669],{"class":606},[601,1541,611],{"class":610},[601,1543,625],{"class":614},[601,1545,618],{"class":606},[601,1547,630],{"class":621},[601,1549,1516],{"class":614},[601,1551,618],{"class":606},[601,1553,1554],{"class":621},"\"design\"",[601,1556,656],{"class":614},[601,1558,618],{"class":606},[601,1560,1528],{"class":621},[601,1562,1563],{"class":606},">Design\u003C\u002F",[601,1565,611],{"class":610},[601,1567,638],{"class":606},[601,1569,1570,1572,1574],{"class":219,"line":689},[601,1571,712],{"class":606},[601,1573,1492],{"class":610},[601,1575,638],{"class":606},[601,1577,1578],{"class":219,"line":709},[601,1579,723],{"emptyLinePlaceholder":722},[601,1581,1582,1584,1586,1588,1590,1593],{"class":219,"line":719},[601,1583,607],{"class":606},[601,1585,51],{"class":610},[601,1587,656],{"class":614},[601,1589,618],{"class":606},[601,1591,1592],{"class":621},"\"cards\"",[601,1594,638],{"class":606},[601,1596,1597,1599,1601,1603,1605,1608,1611,1613,1615,1618,1620,1623],{"class":219,"line":726},[601,1598,669],{"class":606},[601,1600,54],{"class":610},[601,1602,656],{"class":614},[601,1604,618],{"class":606},[601,1606,1607],{"class":621},"\"card\"",[601,1609,1610],{"class":614}," data-tag",[601,1612,618],{"class":606},[601,1614,1554],{"class":621},[601,1616,1617],{"class":614}," style",[601,1619,618],{"class":606},[601,1621,1622],{"class":621},"\"view-transition-name: card-1\"",[601,1624,638],{"class":606},[601,1626,1627,1630,1632,1635,1637],{"class":219,"line":736},[601,1628,1629],{"class":606},"    \u003C",[601,1631,580],{"class":610},[601,1633,1634],{"class":606},">Colour systems\u003C\u002F",[601,1636,580],{"class":610},[601,1638,638],{"class":606},[601,1640,1641,1643,1645,1648,1650],{"class":219,"line":765},[601,1642,1629],{"class":606},[601,1644,14],{"class":610},[601,1646,1647],{"class":606},">Token naming for themeable palettes.\u003C\u002F",[601,1649,14],{"class":610},[601,1651,638],{"class":606},[601,1653,1654,1657,1659],{"class":219,"line":786},[601,1655,1656],{"class":606},"  \u003C\u002F",[601,1658,54],{"class":610},[601,1660,638],{"class":606},[601,1662,1663,1665,1667,1669,1671,1673,1675,1677,1680,1682,1684,1687],{"class":219,"line":791},[601,1664,669],{"class":606},[601,1666,54],{"class":610},[601,1668,656],{"class":614},[601,1670,618],{"class":606},[601,1672,1607],{"class":621},[601,1674,1610],{"class":614},[601,1676,618],{"class":606},[601,1678,1679],{"class":621},"\"code\"",[601,1681,1617],{"class":614},[601,1683,618],{"class":606},[601,1685,1686],{"class":621},"\"view-transition-name: card-2\"",[601,1688,638],{"class":606},[601,1690,1691,1693,1695,1698,1700],{"class":219,"line":814},[601,1692,1629],{"class":606},[601,1694,580],{"class":610},[601,1696,1697],{"class":606},">Layout primitives\u003C\u002F",[601,1699,580],{"class":610},[601,1701,638],{"class":606},[601,1703,1704,1706,1708,1711,1713],{"class":219,"line":821},[601,1705,1629],{"class":606},[601,1707,14],{"class":610},[601,1709,1710],{"class":606},">Composable spacing and alignment.\u003C\u002F",[601,1712,14],{"class":610},[601,1714,638],{"class":606},[601,1716,1717,1719,1721],{"class":219,"line":836},[601,1718,1656],{"class":606},[601,1720,54],{"class":610},[601,1722,638],{"class":606},[601,1724,1725,1727,1729,1731,1733,1735,1737,1739,1741,1743,1745,1748],{"class":219,"line":852},[601,1726,669],{"class":606},[601,1728,54],{"class":610},[601,1730,656],{"class":614},[601,1732,618],{"class":606},[601,1734,1607],{"class":621},[601,1736,1610],{"class":614},[601,1738,618],{"class":606},[601,1740,1554],{"class":621},[601,1742,1617],{"class":614},[601,1744,618],{"class":606},[601,1746,1747],{"class":621},"\"view-transition-name: card-3\"",[601,1749,638],{"class":606},[601,1751,1752,1754,1756,1759,1761],{"class":219,"line":861},[601,1753,1629],{"class":606},[601,1755,580],{"class":610},[601,1757,1758],{"class":606},">Motion tokens\u003C\u002F",[601,1760,580],{"class":610},[601,1762,638],{"class":606},[601,1764,1765,1767,1769,1772,1774],{"class":219,"line":867},[601,1766,1629],{"class":606},[601,1768,14],{"class":610},[601,1770,1771],{"class":606},">Durations and easing as custom properties.\u003C\u002F",[601,1773,14],{"class":610},[601,1775,638],{"class":606},[601,1777,1778,1780,1782],{"class":219,"line":883},[601,1779,1656],{"class":606},[601,1781,54],{"class":610},[601,1783,638],{"class":606},[601,1785,1786,1788,1790],{"class":219,"line":896},[601,1787,712],{"class":606},[601,1789,51],{"class":610},[601,1791,638],{"class":606},[592,1793,1795],{"className":917,"code":1794,"language":919,"meta":597,"style":597},".cards {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n  gap: 1rem;\n}\n\n.card {\n  padding: 1rem;\n  border: 1px solid currentColor;\n  border-radius: 12px;\n  \u002F* Grouped so one rule retimes every card's group animation. *\u002F\n  view-transition-class: card;\n}\n\n.card[hidden] { display: none; }\n\n\u002F* The group carries position and size. Slow it slightly so the travel reads. *\u002F\n::view-transition-group(.card) {\n  animation-duration: 320ms;\n  animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);\n}\n\n\u002F* Cards that leave should shrink away rather than just fading in place. *\u002F\n@keyframes card-exit {\n  to { opacity: 0; transform: scale(0.92); }\n}\n::view-transition-old(.card) {\n  animation: card-exit 200ms ease-in both;\n}\n\n\u002F* Cards that arrive fade up from slightly below. *\u002F\n@keyframes card-enter {\n  from { opacity: 0; transform: translateY(8px); }\n}\n::view-transition-new(.card) {\n  animation: card-enter 260ms 60ms ease-out both;\n}\n\n\u002F* The overlay itself: keep a solid backdrop so partly transparent\n   snapshots never reveal the live DOM mid-animation. *\u002F\n::view-transition {\n  background-color: Canvas;\n}\n",[23,1796,1797,1804,1815,1826,1837,1848,1884,1897,1901,1905,1912,1924,1941,1955,1960,1968,1972,1976,1997,2001,2006,2016,2030,2059,2064,2069,2075,2085,2114,2119,2129,2150,2155,2160,2166,2176,2206,2211,2221,2246,2251,2256,2262,2268,2279,2288],{"__ignoreMap":597},[601,1798,1799,1802],{"class":219,"line":603},[601,1800,1801],{"class":614},".cards",[601,1803,811],{"class":606},[601,1805,1806,1809,1811,1813],{"class":219,"line":641},[601,1807,1808],{"class":614},"  list-style",[601,1810,935],{"class":606},[601,1812,249],{"class":614},[601,1814,858],{"class":606},[601,1816,1817,1820,1822,1824],{"class":219,"line":666},[601,1818,1819],{"class":614},"  margin",[601,1821,935],{"class":606},[601,1823,1101],{"class":614},[601,1825,858],{"class":606},[601,1827,1828,1831,1833,1835],{"class":219,"line":689},[601,1829,1830],{"class":614},"  padding",[601,1832,935],{"class":606},[601,1834,1101],{"class":614},[601,1836,858],{"class":606},[601,1838,1839,1842,1844,1846],{"class":219,"line":709},[601,1840,1841],{"class":614},"  display",[601,1843,935],{"class":606},[601,1845,938],{"class":614},[601,1847,858],{"class":606},[601,1849,1850,1853,1855,1858,1860,1863,1865,1868,1870,1873,1875,1877,1879,1881],{"class":219,"line":719},[601,1851,1852],{"class":614},"  grid-template-columns",[601,1854,935],{"class":606},[601,1856,1857],{"class":614},"repeat",[601,1859,756],{"class":606},[601,1861,1862],{"class":614},"auto-fill",[601,1864,99],{"class":606},[601,1866,1867],{"class":614},"minmax",[601,1869,756],{"class":606},[601,1871,1872],{"class":614},"220",[601,1874,1017],{"class":739},[601,1876,99],{"class":606},[601,1878,949],{"class":614},[601,1880,952],{"class":739},[601,1882,1883],{"class":606},"));\n",[601,1885,1886,1889,1891,1893,1895],{"class":219,"line":726},[601,1887,1888],{"class":614},"  gap",[601,1890,935],{"class":606},[601,1892,949],{"class":614},[601,1894,969],{"class":739},[601,1896,858],{"class":606},[601,1898,1899],{"class":219,"line":736},[601,1900,1117],{"class":606},[601,1902,1903],{"class":219,"line":765},[601,1904,723],{"emptyLinePlaceholder":722},[601,1906,1907,1910],{"class":219,"line":786},[601,1908,1909],{"class":614},".card",[601,1911,811],{"class":606},[601,1913,1914,1916,1918,1920,1922],{"class":219,"line":791},[601,1915,1830],{"class":614},[601,1917,935],{"class":606},[601,1919,949],{"class":614},[601,1921,969],{"class":739},[601,1923,858],{"class":606},[601,1925,1926,1929,1931,1933,1935,1937,1939],{"class":219,"line":814},[601,1927,1928],{"class":614},"  border",[601,1930,935],{"class":606},[601,1932,949],{"class":614},[601,1934,1017],{"class":739},[601,1936,1020],{"class":614},[601,1938,1023],{"class":614},[601,1940,858],{"class":606},[601,1942,1943,1946,1948,1951,1953],{"class":219,"line":821},[601,1944,1945],{"class":614},"  border-radius",[601,1947,935],{"class":606},[601,1949,1950],{"class":614},"12",[601,1952,1017],{"class":739},[601,1954,858],{"class":606},[601,1956,1957],{"class":219,"line":836},[601,1958,1959],{"class":817},"  \u002F* Grouped so one rule retimes every card's group animation. *\u002F\n",[601,1961,1962,1965],{"class":219,"line":852},[601,1963,1964],{"class":614},"  view-transition-class",[601,1966,1967],{"class":606},": card;\n",[601,1969,1970],{"class":219,"line":861},[601,1971,1117],{"class":606},[601,1973,1974],{"class":219,"line":867},[601,1975,723],{"emptyLinePlaceholder":722},[601,1977,1978,1980,1983,1986,1989,1991,1993,1995],{"class":219,"line":883},[601,1979,1909],{"class":614},[601,1981,1982],{"class":606},"[",[601,1984,1985],{"class":614},"hidden",[601,1987,1988],{"class":606},"] { ",[601,1990,932],{"class":614},[601,1992,935],{"class":606},[601,1994,249],{"class":614},[601,1996,972],{"class":606},[601,1998,1999],{"class":219,"line":896},[601,2000,723],{"emptyLinePlaceholder":722},[601,2002,2003],{"class":219,"line":902},[601,2004,2005],{"class":817},"\u002F* The group carries position and size. Slow it slightly so the travel reads. *\u002F\n",[601,2007,2008,2011,2013],{"class":219,"line":908},[601,2009,2010],{"class":606},"::view-transition-group(",[601,2012,1909],{"class":614},[601,2014,2015],{"class":606},") {\n",[601,2017,2019,2021,2023,2026,2028],{"class":219,"line":2018},22,[601,2020,1071],{"class":614},[601,2022,935],{"class":606},[601,2024,2025],{"class":614},"320",[601,2027,1079],{"class":739},[601,2029,858],{"class":606},[601,2031,2033,2035,2037,2039,2041,2044,2046,2049,2051,2053,2055,2057],{"class":219,"line":2032},23,[601,2034,1086],{"class":614},[601,2036,935],{"class":606},[601,2038,1091],{"class":614},[601,2040,756],{"class":606},[601,2042,2043],{"class":614},"0.32",[601,2045,99],{"class":606},[601,2047,2048],{"class":614},"0.72",[601,2050,99],{"class":606},[601,2052,1101],{"class":614},[601,2054,99],{"class":606},[601,2056,949],{"class":614},[601,2058,762],{"class":606},[601,2060,2062],{"class":219,"line":2061},24,[601,2063,1117],{"class":606},[601,2065,2067],{"class":219,"line":2066},25,[601,2068,723],{"emptyLinePlaceholder":722},[601,2070,2072],{"class":219,"line":2071},26,[601,2073,2074],{"class":817},"\u002F* Cards that leave should shrink away rather than just fading in place. *\u002F\n",[601,2076,2078,2080,2083],{"class":219,"line":2077},27,[601,2079,29],{"class":739},[601,2081,2082],{"class":1147}," card-exit",[601,2084,811],{"class":606},[601,2086,2088,2090,2092,2094,2096,2098,2100,2102,2104,2107,2109,2112],{"class":219,"line":2087},28,[601,2089,1185],{"class":614},[601,2091,929],{"class":606},[601,2093,1160],{"class":614},[601,2095,935],{"class":606},[601,2097,1101],{"class":614},[601,2099,941],{"class":606},[601,2101,322],{"class":614},[601,2103,935],{"class":606},[601,2105,2106],{"class":614},"scale",[601,2108,756],{"class":606},[601,2110,2111],{"class":614},"0.92",[601,2113,1180],{"class":606},[601,2115,2117],{"class":219,"line":2116},29,[601,2118,1117],{"class":606},[601,2120,2122,2125,2127],{"class":219,"line":2121},30,[601,2123,2124],{"class":606},"::view-transition-old(",[601,2126,1909],{"class":614},[601,2128,2015],{"class":606},[601,2130,2132,2134,2137,2140,2142,2145,2148],{"class":219,"line":2131},31,[601,2133,1298],{"class":614},[601,2135,2136],{"class":606},": card-exit ",[601,2138,2139],{"class":614},"200",[601,2141,1079],{"class":739},[601,2143,2144],{"class":614}," ease-in",[601,2146,2147],{"class":614}," both",[601,2149,858],{"class":606},[601,2151,2153],{"class":219,"line":2152},32,[601,2154,1117],{"class":606},[601,2156,2158],{"class":219,"line":2157},33,[601,2159,723],{"emptyLinePlaceholder":722},[601,2161,2163],{"class":219,"line":2162},34,[601,2164,2165],{"class":817},"\u002F* Cards that arrive fade up from slightly below. *\u002F\n",[601,2167,2169,2171,2174],{"class":219,"line":2168},35,[601,2170,29],{"class":739},[601,2172,2173],{"class":1147}," card-enter",[601,2175,811],{"class":606},[601,2177,2179,2181,2183,2185,2187,2189,2191,2193,2195,2198,2200,2202,2204],{"class":219,"line":2178},36,[601,2180,1155],{"class":614},[601,2182,929],{"class":606},[601,2184,1160],{"class":614},[601,2186,935],{"class":606},[601,2188,1101],{"class":614},[601,2190,941],{"class":606},[601,2192,322],{"class":614},[601,2194,935],{"class":606},[601,2196,2197],{"class":614},"translateY",[601,2199,756],{"class":606},[601,2201,208],{"class":614},[601,2203,1017],{"class":739},[601,2205,1180],{"class":606},[601,2207,2209],{"class":219,"line":2208},37,[601,2210,1117],{"class":606},[601,2212,2214,2217,2219],{"class":219,"line":2213},38,[601,2215,2216],{"class":606},"::view-transition-new(",[601,2218,1909],{"class":614},[601,2220,2015],{"class":606},[601,2222,2224,2226,2229,2232,2234,2237,2239,2242,2244],{"class":219,"line":2223},39,[601,2225,1298],{"class":614},[601,2227,2228],{"class":606},": card-enter ",[601,2230,2231],{"class":614},"260",[601,2233,1079],{"class":739},[601,2235,2236],{"class":614}," 60",[601,2238,1079],{"class":739},[601,2240,2241],{"class":614}," ease-out",[601,2243,2147],{"class":614},[601,2245,858],{"class":606},[601,2247,2249],{"class":219,"line":2248},40,[601,2250,1117],{"class":606},[601,2252,2254],{"class":219,"line":2253},41,[601,2255,723],{"emptyLinePlaceholder":722},[601,2257,2259],{"class":219,"line":2258},42,[601,2260,2261],{"class":817},"\u002F* The overlay itself: keep a solid backdrop so partly transparent\n",[601,2263,2265],{"class":219,"line":2264},43,[601,2266,2267],{"class":817},"   snapshots never reveal the live DOM mid-animation. *\u002F\n",[601,2269,2271,2274,2277],{"class":219,"line":2270},44,[601,2272,2273],{"class":606},"::",[601,2275,2276],{"class":610},"view-transition",[601,2278,811],{"class":606},[601,2280,2282,2285],{"class":219,"line":2281},45,[601,2283,2284],{"class":614},"  background-color",[601,2286,2287],{"class":606},": Canvas;\n",[601,2289,2291],{"class":219,"line":2290},46,[601,2292,1117],{"class":606},[14,2294,2295,2296,2298,2299,2302,2303,107],{},"The inline ",[23,2297,64],{}," values are the honest way to write this by hand, and they expose the API's central constraint immediately: each card needs a ",[18,2300,2301],{},"different"," name, which means the names have to come from data. Why that is unavoidable, and what it means for list-to-detail navigation, is the subject of ",[32,2304,2306],{"href":2305},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-names-shared-elements\u002F","view transition names and shared elements",[14,2308,2309,2310,2314],{},"Grid layouts like this one respond well to being paired with container-driven sizing; see ",[32,2311,2313],{"href":2312},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fbuilding-responsive-cards-with-container-queries\u002F","building responsive cards with container queries"," for the layout side of the same component.",[74,2316],{},[77,2318,2320],{"id":2319},"performance-and-accessibility","Performance and accessibility",[14,2322,2323,2326],{},[47,2324,2325],{},"Snapshot cost scales with named elements."," Each name means an additional texture the compositor allocates, uploads, and animates. A dozen named cards is fine. Two hundred named rows in a virtualised table will stutter on mid-range hardware, and the stutter arrives during capture — before any animation has started — so it reads as an input delay rather than a dropped frame. Name the few things that carry meaning, not everything on screen.",[14,2328,2329,2332,2333,99,2335,103,2337,2339,2340,2342,2343,2346,2347,107],{},[47,2330,2331],{},"The animations are compositor-friendly by construction."," The default group animation interpolates ",[23,2334,322],{},[23,2336,316],{},[23,2338,319],{},"; the snapshot animations interpolate ",[23,2341,1160],{},". Snapshots are already textures, so scaling them costs the GPU almost nothing — this is one of the rare cases where animating something size-like is cheap. ",[23,2344,2345],{},"will-change"," is unnecessary and counterproductive here, because the browser has already promoted these to their own layers; the reasoning behind that is laid out in ",[32,2348,2350],{"href":2349},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Fwill-change-and-the-compositor-thread\u002F","will-change and the compositor thread",[14,2352,2353,2356],{},[47,2354,2355],{},"Rendering is suspended during capture."," If the DOM change in your callback is expensive — a synchronous layout of a thousand rows, a blocking data parse — the page is frozen for that entire time and the transition looks broken. Keep the callback to the smallest DOM mutation that produces the new state.",[14,2358,2359,2362,2363,2366,2367,2371,2372,107],{},[47,2360,2361],{},"Accessibility is not automatic."," The snapshot overlay is inert and unreadable by assistive technology, which is correct — screen reader users are told about the new DOM, not the animation. But focus is not managed for you. When a transition swaps a whole view, move focus deliberately to the new content, or keyboard users land nowhere. And large-area motion is exactly the category WCAG 2.3.3 (Animation from Interactions) targets, which is why the reduced-motion story here is more nuanced than ",[23,2364,2365],{},"animation: none"," — see ",[32,2368,2370],{"href":2369},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion\u002F","view transitions with reduced motion"," and the broader recipes in ",[32,2373,2375],{"href":2374},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Freducing-motion-preferences-in-css\u002F","reducing motion preferences in CSS",[74,2377],{},[77,2379,2381],{"id":2380},"devtools-debugging-workflow","DevTools debugging workflow",[14,2383,2384],{},"Because the pseudo-elements exist for a few hundred milliseconds and then vanish, the ordinary inspect-and-tweak loop does not work. Use the animation tooling instead.",[2386,2387,2388,2398,2404,2423,2432],"ol",{},[54,2389,2390,2393,2394,2397],{},[47,2391,2392],{},"Chrome\u002FEdge — Animations panel."," Open DevTools, press ",[23,2395,2396],{},"Ctrl\u002FCmd+Shift+P",", run \"Show Animations\". Trigger the transition. The panel captures every animation in the group, including the user-agent ones, and lists them by pseudo-element name. Clicking one reveals its keyframes and duration.",[54,2399,2400,2403],{},[47,2401,2402],{},"Slow it down."," In the same panel set playback speed to 25% or 10%, then re-trigger. At 10% a 250ms transition runs for two and a half seconds — long enough to see whether a snapshot is squashing, whether a group is travelling to the wrong rectangle, or whether an old snapshot is still opaque when it should be gone.",[54,2405,2406,2409,2410,2412,2413,2415,2416,99,2418,103,2420,2422],{},[47,2407,2408],{},"Freeze it in the Elements tree."," With the animation paused, the ",[23,2411,217],{}," subtree is visible under the document root in Elements. You can select ",[23,2414,312],{}," and read its computed ",[23,2417,316],{},[23,2419,319],{},[23,2421,322],{}," at that instant — this is the fastest way to confirm the browser measured what you expected.",[54,2424,2425,2428,2429,2431],{},[47,2426,2427],{},"Check for duplicate names."," If a transition silently does nothing, open the console. Engines log a warning when two elements share a ",[23,2430,64],{}," in the same snapshot, and that condition aborts the whole transition rather than degrading it.",[54,2433,2434,2437],{},[47,2435,2436],{},"Safari — Web Inspector."," The Elements tree exposes the same pseudo-element subtree while paused, though the dedicated animation timeline is less detailed than Chrome's. Testing there matters, because Safari's snapshot rasterisation of text at fractional scales differs visibly from Chromium's.",[74,2439],{},[77,2441,2443],{"id":2442},"browser-compatibility","Browser compatibility",[379,2445,2446,2459],{},[382,2447,2448],{},[385,2449,2450,2453,2456],{},[388,2451,2452],{},"Feature",[388,2454,2455],{},"Support as of mid-2026",[388,2457,2458],{},"Notes",[398,2460,2461,2472,2486,2497,2510],{},[385,2462,2463,2466,2469],{},[403,2464,2465],{},"Same-document view transitions",[403,2467,2468],{},"Chrome 111+, Edge 111+, Firefox 144+, Safari 18+",[403,2470,2471],{},"Available in every current engine",[385,2473,2474,2480,2483],{},[403,2475,2476,2479],{},[23,2477,2478],{},"::view-transition-*"," pseudo-elements",[403,2481,2482],{},"Ships with same-document support",[403,2484,2485],{},"Same availability as above",[385,2487,2488,2492,2494],{},[403,2489,2490],{},[23,2491,64],{},[403,2493,2482],{},[403,2495,2496],{},"Custom ident values",[385,2498,2499,2504,2507],{},[403,2500,2501,2502],{},"Cross-document ",[23,2503,1440],{},[403,2505,2506],{},"Chrome 126+, Edge 126+, Safari 18.2+",[403,2508,2509],{},"Not supported in Firefox; the one remaining gap",[385,2511,2512,2516,2519],{},[403,2513,2514],{},[23,2515,425],{},[403,2517,2518],{},"Chromium only at the time of writing",[403,2520,2521],{},"Selector convenience; the per-name selectors are the fallback",[14,2523,2524,2525,2527],{},"Read the table as two separate stories. Same-document transitions are done: Chromium shipped them in 111, Safari in 18, and Firefox in 144, so the feature is interoperable and the only population without it is browser versions older than those. The cross-document half is not: ",[23,2526,1440],{}," is Chromium 126 and Safari 18.2, and Firefox has not shipped it. That is now the single meaningful gap in this section, and it is why a multi-page navigation must still work perfectly with no transition at all — describe cross-document transitions in a project as an enhancement some browsers apply, and never let a navigation depend on one.",[14,2529,2530,2531,2534,2535,2538,2539,2542,2543,2546],{},"There is no useful ",[23,2532,2533],{},"@supports"," test for the JavaScript entry point, so feature-detect in script with ",[23,2536,2537],{},"if (!document.startViewTransition)",". For the at-rule you can use ",[23,2540,2541],{},"@supports at-rule(@view-transition)"," in engines that implement the ",[23,2544,2545],{},"at-rule()"," test, but the safer pattern is simply to let unsupporting browsers ignore the unknown at-rule, which they do silently and harmlessly.",[74,2548],{},[77,2550,2552],{"id":2551},"common-pitfalls","Common pitfalls",[379,2554,2555,2568],{},[382,2556,2557],{},[385,2558,2559,2562,2565],{},[388,2560,2561],{},"Pitfall",[388,2563,2564],{},"Cause",[388,2566,2567],{},"Resolution",[398,2569,2570,2584,2607,2621,2635],{},[385,2571,2572,2575,2581],{},[403,2573,2574],{},"Transition aborts with nothing happening",[403,2576,2577,2578,2580],{},"Two elements share one ",[23,2579,64],{}," in a single snapshot",[403,2582,2583],{},"Names must be unique per capture; derive them from record IDs and clear them when off-screen",[385,2585,2586,2589,2594],{},[403,2587,2588],{},"Text distorts as a box grows",[403,2590,2591,2592],{},"Snapshots are replaced elements defaulting to ",[23,2593,366],{},[403,2595,2596,2597,2599,2600,346,2603,2606],{},"Set ",[23,2598,370],{}," on both ",[23,2601,2602],{},"-old()",[23,2604,2605],{},"-new()",", or animate a wrapper instead of the text",[385,2608,2609,2612,2615],{},[403,2610,2611],{},"Sticky or fixed header jumps to the top",[403,2613,2614],{},"Snapshots are captured relative to the viewport and painted in the overlay, losing fixed positioning",[403,2616,2617,2618,2620],{},"Give the header its own ",[23,2619,64],{}," so it becomes its own group and stays put",[385,2622,2623,2626,2632],{},[403,2624,2625],{},"Page appears frozen for a beat before animating",[403,2627,2628,2629,2631],{},"Expensive DOM work inside the ",[23,2630,873],{}," callback while rendering is suspended",[403,2633,2634],{},"Move data fetching and parsing outside the callback; mutate only",[385,2636,2637,2643,2648],{},[403,2638,2639,2640,2642],{},"Custom keyframes on ",[23,2641,2602],{}," cause a flash at the end",[403,2644,2645,2647],{},[23,2646,106],{}," not set, so the snapshot snaps back to its start value",[403,2649,2650,2651,2653,2654,2657,2658,2660],{},"Add ",[23,2652,1330],{}," (or ",[23,2655,2656],{},"forwards",") to the ",[23,2659,94],{}," shorthand",[74,2662],{},[77,2664,2666],{"id":2665},"faq","FAQ",[14,2668,2669,2672,2673,2675,2676,2678,2679,2682],{},[47,2670,2671],{},"Is the View Transitions API a CSS feature or a JavaScript feature?","\nBoth. A same-document transition is started from JavaScript with ",[23,2674,589],{},", and cross-document transitions are opted into with the ",[23,2677,1440],{}," at-rule. Everything about how the transition ",[18,2680,2681],{},"looks"," — timing, easing, keyframes, which elements move independently — is CSS applied to generated pseudo-elements.",[14,2684,2685,2688],{},[47,2686,2687],{},"What does the browser actually animate during a view transition?","\nFlat snapshot images, not live DOM. The browser captures the old rendering, applies your DOM change, captures the new rendering, then animates replaced elements built from those two captures in a separate overlay tree above the page.",[14,2690,2691,2694,2695,2697],{},[47,2692,2693],{},"Why does my whole page cross-fade instead of just the element I named?","\nBecause everything without an explicit ",[23,2696,64],{}," is captured together as a single root snapshot. Naming an element pulls it out of the root snapshot into its own group so it can animate independently.",[14,2699,2700,2703],{},[47,2701,2702],{},"Do I need to write any CSS for a view transition to work?","\nNo. With no CSS the user agent applies a 250ms cross-fade to the root snapshot pair. You write CSS only when you want different timing, different easing, or independent motion for named elements.",[14,2705,2706,2709,2710,2712],{},[47,2707,2708],{},"Which browsers support view transitions in mid-2026?","\nSame-document view transitions ship in Chrome and Edge 111+, Safari 18+, and Firefox 144+, so they are available in every current engine. The cross-document ",[23,2711,1440],{}," rule is narrower: Chrome and Edge 126+ and Safari 18.2+, with no Firefox support yet.",[74,2714],{},[77,2716,2718],{"id":2717},"related","Related",[51,2720,2721,2726,2732,2738,2748,2755],{},[54,2722,2723,2725],{},[32,2724,2465],{"href":1385}," — the CSS you write to replace the default cross-fade.",[54,2727,2728,2731],{},[32,2729,2730],{"href":2305},"View transition names and shared elements"," — morphing a thumbnail into a hero, and the uniqueness rule that constrains it.",[54,2733,2734,2737],{},[32,2735,2736],{"href":2369},"View transitions with reduced motion"," — swapping travel for a fade instead of switching the transition off.",[54,2739,2740,2744,2745,2747],{},[32,2741,2743],{"href":2742},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002F","Keyframe Animation Patterns"," — the ",[23,2746,29],{}," techniques you attach to the snapshot pseudo-elements.",[54,2749,2750,2754],{},[32,2751,2753],{"href":2752},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002F","Scroll-driven animations"," — the other recent API that hands animation timing to the browser.",[54,2756,2757,2760],{},[32,2758,2759],{"href":2312},"Building responsive cards with container queries"," — the layout side of the card grid used in this guide.",[2762,2763,2764],"style",{},"html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .sKwhi, html code.shiki .sKwhi{--shiki-default:#622CBC;--shiki-dark:#DBB7FF}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}",{"title":597,"searchDepth":641,"depth":641,"links":2766},[2767,2768,2769,2770,2771,2778,2779,2780,2781,2782,2783,2784],{"id":79,"depth":641,"text":80},{"id":139,"depth":641,"text":140},{"id":287,"depth":641,"text":288},{"id":376,"depth":641,"text":377},{"id":577,"depth":641,"text":578,"children":2772},[2773,2774,2775,2776,2777],{"id":582,"depth":666,"text":583},{"id":1047,"depth":666,"text":1048},{"id":1131,"depth":666,"text":1132},{"id":1389,"depth":666,"text":1390},{"id":1426,"depth":666,"text":1427},{"id":1476,"depth":641,"text":1477},{"id":2319,"depth":641,"text":2320},{"id":2380,"depth":641,"text":2381},{"id":2442,"depth":641,"text":2443},{"id":2551,"depth":641,"text":2552},{"id":2665,"depth":641,"text":2666},{"id":2717,"depth":641,"text":2718},"Learn the View Transitions API as CSS: the snapshot model, the ::view-transition pseudo-element tree, view-transition-name, and cross-document @view-transition.","md",{"pageTitle":2788,"datePublished":2789,"dateModified":2789,"faq":2790},"View Transitions for CSS Developers","2026-07-20",[2791,2793,2795,2797,2799],{"q":2671,"a":2792},"Both. A same-document transition is started from JavaScript with document.startViewTransition(), and cross-document transitions are opted into with the @view-transition at-rule. Everything about how the transition looks is CSS applied to generated pseudo-elements.",{"q":2687,"a":2794},"Flat snapshot images, not live DOM. The browser captures the old rendering, applies your DOM change, captures the new rendering, then animates replaced elements built from those two captures in a separate overlay tree above the page.",{"q":2693,"a":2796},"Because everything without an explicit view-transition-name is captured together as a single root snapshot. Naming an element pulls it out of the root snapshot into its own group so it can animate independently.",{"q":2702,"a":2798},"No. With no CSS the user agent applies a 250ms cross-fade to the root snapshot pair. You write CSS only when you want different timing, different easing, or independent motion for named elements.",{"q":2708,"a":2800},"Same-document view transitions ship in Chrome and Edge 111+, Safari 18+, and Firefox 144+, so they are available in every current engine. The cross-document @view-transition rule is narrower: Chrome and Edge 126+ and Safari 18.2+, with no Firefox support yet.","\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers",{"title":5,"description":2785},"css-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Findex","y5XU4LFSBdZSiThgAlHJ2AlLWygk1jTH1wQM1hIywj4",[2806,2809,2812,2815,2818,2821,2824,2827,2830,2833,2836,2839,2842,2845,2848,2851,2854,2857,2860,2863,2866,2869,2872,2875,2878,2881,2884,2887,2890,2893,2896,2899,2902,2905,2908,2911,2914,2917,2920,2923,2926,2929,2932,2933,2936,2939,2942,2945,2948,2951,2954,2957,2960,2963,2966,2969,2972,2975,2978,2981,2984,2987,2990,2993,2996,2999,3002,3005,3008,3011,3014,3017,3020,3023,3026,3029,3032,3035,3038,3041,3044,3047,3050,3053,3056,3059,3062,3065],{"path":2807,"title":2808},"\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":2810,"title":2811},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":2813,"title":2814},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":2816,"title":2817},"\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":2819,"title":2820},"\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":2822,"title":2823},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":2825,"title":2826},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":2828,"title":2829},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":2831,"title":2832},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":2834,"title":2835},"\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":2837,"title":2838},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":2840,"title":2841},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":2843,"title":2844},"\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":2846,"title":2847},"\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":2849,"title":2850},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":2852,"title":2853},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":2855,"title":2856},"\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":2858,"title":2859},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":2861,"title":2862},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":2864,"title":2865},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":2867,"title":2868},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":2870,"title":2871},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":2873,"title":2874},"\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":2876,"title":2877},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":2879,"title":2880},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":2882,"title":2883},"\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":2885,"title":2886},"\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":2888,"title":2889},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":2891,"title":2892},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":2894,"title":2895},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":2897,"title":2898},"\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":2900,"title":2901},"\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":2903,"title":2904},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":2906,"title":2907},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":2909,"title":2910},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":2912,"title":2913},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":2915,"title":2916},"\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":2918,"title":2919},"\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":2921,"title":2922},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":2924,"title":2925},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":2927,"title":2928},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":2930,"title":2931},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":2801,"title":5},{"path":2934,"title":2935},"\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":2937,"title":2938},"\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":2940,"title":2941},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":2943,"title":2944},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":2946,"title":2947},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":2949,"title":2950},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":2952,"title":2953},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":2955,"title":2956},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":2958,"title":2959},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":2961,"title":2962},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":2964,"title":2965},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":2967,"title":2968},"\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":2970,"title":2971},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":2973,"title":2974},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":2976,"title":2977},"\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":2979,"title":2980},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":2982,"title":2983},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":2985,"title":2986},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":2988,"title":2989},"\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":2991,"title":2992},"\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":2994,"title":2995},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":2997,"title":2998},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":3000,"title":3001},"\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":3003,"title":3004},"\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":3006,"title":3007},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":3009,"title":3010},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":3012,"title":3013},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":3015,"title":3016},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":3018,"title":3019},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":3021,"title":3022},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":3024,"title":3025},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":3027,"title":3028},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":3030,"title":3031},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":3033,"title":3034},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":3036,"title":3037},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":3039,"title":3040},"\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":3042,"title":3043},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":3045,"title":3046},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":3048,"title":3049},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":3051,"title":3052},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":3054,"title":3055},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":3057,"title":3058},"\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":3060,"title":3061},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":3063,"title":3064},"\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":3066,"title":3067},"\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",1784566156667]