[{"data":1,"prerenderedAt":2475},["ShallowReactive",2],{"page-\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-names-shared-elements\u002F":3,"content-all-pages":2212},{"id":4,"title":5,"body":6,"description":2194,"extension":2195,"meta":2196,"navigation":430,"path":2208,"seo":2209,"stem":2210,"__hash__":2211},"content\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-names-shared-elements\u002Findex.md","view-transition-name and Shared Elements: Morphing a Thumbnail into a Hero",{"type":7,"value":8,"toc":2184},"minimark",[9,13,28,31,34,39,46,65,68,75,77,81,92,95,139,142,276,279,283,285,289,292,1945,1952,1954,1958,1980,1992,2010,2012,2016,2019,2060,2067,2078,2080,2084,2093,2095,2099,2108,2121,2135,2141,2143,2147,2181],[10,11,5],"h1",{"id":12},"view-transition-name-and-shared-elements-morphing-a-thumbnail-into-a-hero",[14,15,16,17,21,22,27],"p",{},"The interaction is familiar from native apps: tap a small square in a list and it expands into the full-width image at the top of a detail view, carrying the eye with it. Done with JavaScript this needs measurement of both rectangles, a cloned node positioned over the page, a FLIP calculation, and cleanup. Done with ",[18,19,20],"code",{},"view-transition-name"," it is one declaration on each of the two elements. This page, part of ",[23,24,26],"a",{"href":25},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002F","View Transitions for CSS Developers",", covers how that matching works and the one constraint that shapes every real implementation of it.",[14,29,30],{},"The scenario is narrow and specific: a grid of thumbnails, one of which becomes the hero of the view that replaces the grid. Everything below follows from that.",[32,33],"hr",{},[35,36,38],"h2",{"id":37},"why-a-name-rather-than-a-selector","Why a name rather than a selector",[14,40,41,42,45],{},"The property does not describe an animation. It assigns an identity. When the browser captures the before state it records \"there was a box called ",[18,43,44],{},"hero-7"," at these coordinates with this content\"; when it captures the after state it records the same for whatever box carries that name then. Matching is by string, and by string alone.",[14,47,48,49,52,53,56,57,60,61,64],{},"That has an immediate and slightly surprising consequence: the two elements need have nothing in common. A ",[18,50,51],{},"\u003Cimg>"," inside an ",[18,54,55],{},"\u003Cli>"," can be matched with a ",[18,58,59],{},"\u003Cfigure>"," inside a ",[18,62,63],{},"\u003Cheader>",". Different tags, different ancestors, different stylesheets. The browser is not tracking a node across the change — the old node may well have been destroyed. It is tracking a label.",[14,66,67],{},"This is why the approach beats a scripted equivalent. A FLIP animation has to hold a reference to a real element, which forces the old and new views to coexist in the DOM for at least a frame, which in turn forces you to manage two competing layouts. Naming sidesteps all of it: the old element can be gone entirely by the time the new one is measured.",[14,69,70,71,74],{},"The tradeoff is that identity is now your responsibility. There is no ",[18,72,73],{},":has()","-style inference, no automatic pairing by position. If you get a name wrong, the elements do not morph — they cross-fade like everything else, silently.",[32,76],{},[35,78,80],{"id":79},"the-uniqueness-constraint","The uniqueness constraint",[14,82,83,84,86,87,91],{},"A ",[18,85,20],{}," must be unique among all elements captured in a single snapshot. Not unique per page, not unique per component — unique per capture. If two rendered elements carry the same name at the moment the browser captures, the transition is ",[88,89,90],"strong",{},"skipped entirely",". It does not fall back to a cross-fade, and it does not choose one arbitrarily; the whole operation aborts and the DOM change happens with no animation.",[14,93,94],{},"This is easy to violate without noticing, because the natural first instinct is to write a component stylesheet:",[96,97,102],"pre",{"className":98,"code":99,"language":100,"meta":101,"style":101},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u002F* Wrong: every card in the grid now claims the same identity. *\u002F\n.card__image {\n  view-transition-name: hero;\n}\n","css","",[18,103,104,113,124,133],{"__ignoreMap":101},[105,106,109],"span",{"class":107,"line":108},"line",1,[105,110,112],{"class":111},"sLBg1","\u002F* Wrong: every card in the grid now claims the same identity. *\u002F\n",[105,114,116,120],{"class":107,"line":115},2,[105,117,119],{"class":118},"s-5SL",".card__image",[105,121,123],{"class":122},"suds8"," {\n",[105,125,127,130],{"class":107,"line":126},3,[105,128,129],{"class":118},"  view-transition-name",[105,131,132],{"class":122},": hero;\n",[105,134,136],{"class":107,"line":135},4,[105,137,138],{"class":122},"}\n",[14,140,141],{},"With one card on screen this works beautifully. With twelve it silently does nothing, which makes it a nasty bug to catch in review — the code looks correct and the failure is an absence.",[143,144,150,151,150,155,150,159,150,166,150,172,150,176,150,188,150,191,150,200,150,205,150,211,150,216,150,219,150,222,150,225,150,229,150,233,150,236,150,244,150,250,150,255,150,259],"svg",{"viewBox":145,"role":146,"ariaLabel":147,"xmlns":148,"style":149},"0 0 720 380","img","A named thumbnail in the before snapshot matching a named hero image in the after snapshot","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0","\n  ",[152,153,154],"title",{},"Matching one name across two captures",[156,157,158],"desc",{},"The before capture holds three thumbnails of which one carries a unique name; the after capture holds a single hero box with the same name, and the two are matched.",[160,161,165],"text",{"x":162,"y":163,"style":164},"360","26","text-anchor:middle;fill:currentColor;font:700 18px sans-serif","One unique name, matched across two captures",[160,167,171],{"x":168,"y":169,"style":170},"169","56","text-anchor:middle;fill:#7aa2ff;font:600 14px sans-serif","before capture",[160,173,175],{"x":174,"y":169,"style":170},"551","after capture",[177,178],"rect",{"x":179,"y":180,"width":181,"height":182,"rx":183,"fill":184,"stroke":185,"strokeWidth":186,"opacity":187},"24","66","290","228","12","none","currentColor","1.5","0.45",[177,189],{"x":190,"y":180,"width":181,"height":182,"rx":183,"fill":184,"stroke":185,"strokeWidth":186,"opacity":187},"406",[177,192],{"x":193,"y":194,"width":195,"height":196,"rx":197,"fill":184,"stroke":185,"strokeWidth":198,"opacity":199},"48","92","242","46","8","1.2","0.6",[160,201,204],{"x":168,"y":202,"style":203},"121","text-anchor:middle;fill:currentColor;font:12px ui-monospace,monospace","thumb (no name)",[177,206],{"x":193,"y":207,"width":195,"height":208,"rx":197,"fill":209,"opacity":210},"152","52","#7aa2ff","0.28",[160,212,215],{"x":168,"y":213,"style":214},"173","text-anchor:middle;fill:currentColor;font:11px sans-serif","view-transition-name:",[160,217,44],{"x":168,"y":218,"style":203},"192",[177,220],{"x":193,"y":221,"width":195,"height":196,"rx":197,"fill":184,"stroke":185,"strokeWidth":198,"opacity":199},"218",[160,223,204],{"x":168,"y":224,"style":203},"247",[177,226],{"x":227,"y":228,"width":195,"height":228,"rx":197,"fill":209,"opacity":210},"430","110",[160,230,232],{"x":174,"y":207,"style":231},"text-anchor:middle;fill:currentColor;font:600 14px sans-serif","hero image",[160,234,44],{"x":174,"y":235,"style":203},"180",[107,237],{"x1":238,"y1":239,"x2":240,"y2":241,"stroke":209,"strokeWidth":242,"markerEnd":243},"314","178","398","164","2.5","url(#vtn-arrow)",[160,245,249],{"x":246,"y":247,"style":248},"356","140","text-anchor:middle;fill:currentColor;font:11px sans-serif;opacity:0.8","match",[160,251,254],{"x":162,"y":252,"style":253},"330","text-anchor:middle;fill:currentColor;font:12px sans-serif;opacity:0.75","A duplicate name in either capture aborts the whole transition.",[160,256,258],{"x":162,"y":257,"style":253},"354","Unnamed thumbnails travel inside the root snapshot instead.",[260,261,262,263,150],"defs",{},"\n    ",[264,265,271,272,262],"marker",{"id":266,"markerWidth":267,"markerHeight":267,"refX":268,"refY":269,"orient":270},"vtn-arrow","9","7","4","auto","\n      ",[273,274],"path",{"d":275,"fill":209},"M0 0 L8 4 L0 8 z",[14,277,278],{},"The demo runs the group animation this pairing produces — a box interpolating position and size between the thumbnail rectangle and the hero rectangle.",[280,281],"live-demo",{"name":282},"vt-shared-element-morph",[32,284],{},[35,286,288],{"id":287},"complete-working-implementation","Complete working implementation",[14,290,291],{},"The pattern that survives contact with real data: names are derived from record identifiers, applied only to the item being acted on, and cleared afterwards so the next interaction starts from a clean slate.",[96,293,297],{"className":294,"code":295,"language":296,"meta":101,"style":101},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003C!DOCTYPE html>\n\u003Chtml lang=\"en\">\n\u003Chead>\n\u003Cmeta charset=\"utf-8\">\n\u003Ctitle>Thumbnail to hero morph\u003C\u002Ftitle>\n\u003Cstyle>\n  body { font-family: system-ui, sans-serif; margin: 2rem; }\n\n  .grid {\n    list-style: none; margin: 0; padding: 0;\n    display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;\n  }\n  .thumb {\n    width: 100%; aspect-ratio: 1; object-fit: cover;\n    border-radius: 10px; display: block; cursor: pointer;\n  }\n\n  .detail { display: none; }\n  .detail[data-open] { display: block; }\n  .grid[data-hidden] { display: none; }\n\n  .hero {\n    width: 100%; aspect-ratio: 16 \u002F 9; object-fit: cover;\n    border-radius: 14px; display: block;\n  }\n\n  \u002F* The name is set from script on exactly one element at a time, so no\n     stylesheet rule assigns it. See the toggle() function below. *\u002F\n\n  \u002F* Both captures are replaced elements. Without cover, the square\n     thumbnail capture is stretched into the 16:9 hero box and the\n     content visibly distorts mid-morph. *\u002F\n  ::view-transition-old(hero-shot),\n  ::view-transition-new(hero-shot) {\n    object-fit: cover;\n    \u002F* Hold the incoming image fully opaque so the morph reads as one\n       object changing shape rather than two images cross-fading. *\u002F\n    mix-blend-mode: normal;\n  }\n  ::view-transition-old(hero-shot) { animation: none; opacity: 0; }\n  ::view-transition-new(hero-shot) { animation: none; opacity: 1; }\n\n  \u002F* The group is what travels and resizes. Give it a longer, softer\n     curve than the default so the distance is legible. *\u002F\n  ::view-transition-group(hero-shot) {\n    animation-duration: 420ms;\n    animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);\n  }\n\u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n\n\u003Cul class=\"grid\" id=\"grid\">\n  \u003Cli>\u003Cimg class=\"thumb\" data-id=\"7\"  src=\"\u002Fimg\u002F7.jpg\"  alt=\"Coastal path\">\u003C\u002Fli>\n  \u003Cli>\u003Cimg class=\"thumb\" data-id=\"12\" src=\"\u002Fimg\u002F12.jpg\" alt=\"Harbour at dusk\">\u003C\u002Fli>\n  \u003Cli>\u003Cimg class=\"thumb\" data-id=\"19\" src=\"\u002Fimg\u002F19.jpg\" alt=\"Pine ridge\">\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Csection class=\"detail\" id=\"detail\" tabindex=\"-1\">\n  \u003Cimg class=\"hero\" id=\"hero\" src=\"\" alt=\"\">\n  \u003Ch1 id=\"heroTitle\">\u003C\u002Fh1>\n  \u003Cbutton type=\"button\" id=\"back\">Back to grid\u003C\u002Fbutton>\n\u003C\u002Fsection>\n\n\u003Cscript>\n  const grid = document.getElementById('grid');\n  const detail = document.getElementById('detail');\n  const hero = document.getElementById('hero');\n  const title = document.getElementById('heroTitle');\n  let active = null;\n\n  function open(img) {\n    active = img;\n    \u002F\u002F Assign the shared identity to exactly two elements, one per capture.\n    img.style.viewTransitionName = 'hero-shot';\n    hero.style.viewTransitionName = 'hero-shot';\n    hero.src = img.src;\n    hero.alt = img.alt;\n    title.textContent = img.alt;\n    grid.setAttribute('data-hidden', '');\n    detail.setAttribute('data-open', '');\n  }\n\n  function close() {\n    grid.removeAttribute('data-hidden');\n    detail.removeAttribute('data-open');\n  }\n\n  function run(fn) {\n    if (!document.startViewTransition) { fn(); return; }\n    \u002F\u002F finished resolves once the overlay is torn down; clear names then so\n    \u002F\u002F the next open() never finds two elements holding hero-shot.\n    document.startViewTransition(fn).finished.then(() => {\n      if (active) active.style.viewTransitionName = '';\n      hero.style.viewTransitionName = '';\n    });\n  }\n\n  grid.addEventListener('click', e => {\n    const img = e.target.closest('.thumb');\n    if (img) run(() => { open(img); detail.focus(); });\n  });\n\n  document.getElementById('back').addEventListener('click', () => {\n    if (active) active.style.viewTransitionName = 'hero-shot';\n    hero.style.viewTransitionName = 'hero-shot';\n    run(close);\n  });\n\u003C\u002Fscript>\n\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html",[18,298,299,314,333,342,359,373,383,425,432,440,471,520,526,534,569,605,610,615,631,653,673,678,686,721,743,748,753,759,765,770,776,782,788,800,811,823,829,835,848,853,881,906,911,917,923,933,949,981,986,996,1005,1015,1020,1045,1097,1143,1187,1196,1201,1232,1267,1287,1317,1326,1331,1341,1367,1388,1409,1430,1446,1451,1467,1478,1484,1497,1509,1520,1531,1541,1562,1581,1586,1591,1602,1616,1629,1634,1639,1654,1679,1685,1691,1714,1730,1742,1748,1753,1758,1782,1806,1835,1841,1846,1875,1888,1899,1908,1913,1922,1927,1936],{"__ignoreMap":101},[105,300,301,304,308,311],{"class":107,"line":108},[105,302,303],{"class":122},"\u003C!",[105,305,307],{"class":306},"sne4z","DOCTYPE",[105,309,310],{"class":118}," html",[105,312,313],{"class":122},">\n",[105,315,316,319,321,324,327,331],{"class":107,"line":115},[105,317,318],{"class":122},"\u003C",[105,320,296],{"class":306},[105,322,323],{"class":118}," lang",[105,325,326],{"class":122},"=",[105,328,330],{"class":329},"sT6z2","\"en\"",[105,332,313],{"class":122},[105,334,335,337,340],{"class":107,"line":126},[105,336,318],{"class":122},[105,338,339],{"class":306},"head",[105,341,313],{"class":122},[105,343,344,346,349,352,354,357],{"class":107,"line":135},[105,345,318],{"class":122},[105,347,348],{"class":306},"meta",[105,350,351],{"class":118}," charset",[105,353,326],{"class":122},[105,355,356],{"class":329},"\"utf-8\"",[105,358,313],{"class":122},[105,360,362,364,366,369,371],{"class":107,"line":361},5,[105,363,318],{"class":122},[105,365,152],{"class":306},[105,367,368],{"class":122},">Thumbnail to hero morph\u003C\u002F",[105,370,152],{"class":306},[105,372,313],{"class":122},[105,374,376,378,381],{"class":107,"line":375},6,[105,377,318],{"class":122},[105,379,380],{"class":306},"style",[105,382,313],{"class":122},[105,384,386,389,392,395,398,401,404,407,410,413,415,418,422],{"class":107,"line":385},7,[105,387,388],{"class":306},"  body",[105,390,391],{"class":122}," { ",[105,393,394],{"class":118},"font-family",[105,396,397],{"class":122},": ",[105,399,400],{"class":118},"system-ui",[105,402,403],{"class":122},", ",[105,405,406],{"class":118},"sans-serif",[105,408,409],{"class":122},"; ",[105,411,412],{"class":118},"margin",[105,414,397],{"class":122},[105,416,417],{"class":118},"2",[105,419,421],{"class":420},"sHUrx","rem",[105,423,424],{"class":122},"; }\n",[105,426,428],{"class":107,"line":427},8,[105,429,431],{"emptyLinePlaceholder":430},true,"\n",[105,433,435,438],{"class":107,"line":434},9,[105,436,437],{"class":118},"  .grid",[105,439,123],{"class":122},[105,441,443,446,448,450,452,454,456,459,461,464,466,468],{"class":107,"line":442},10,[105,444,445],{"class":118},"    list-style",[105,447,397],{"class":122},[105,449,184],{"class":118},[105,451,409],{"class":122},[105,453,412],{"class":118},[105,455,397],{"class":122},[105,457,458],{"class":118},"0",[105,460,409],{"class":122},[105,462,463],{"class":118},"padding",[105,465,397],{"class":122},[105,467,458],{"class":118},[105,469,470],{"class":122},";\n",[105,472,474,477,479,482,484,487,489,492,495,498,500,503,506,509,512,514,516,518],{"class":107,"line":473},11,[105,475,476],{"class":118},"    display",[105,478,397],{"class":122},[105,480,481],{"class":118},"grid",[105,483,409],{"class":122},[105,485,486],{"class":118},"grid-template-columns",[105,488,397],{"class":122},[105,490,491],{"class":118},"repeat",[105,493,494],{"class":122},"(",[105,496,497],{"class":118},"3",[105,499,403],{"class":122},[105,501,502],{"class":118},"1",[105,504,505],{"class":420},"fr",[105,507,508],{"class":122},"); ",[105,510,511],{"class":118},"gap",[105,513,397],{"class":122},[105,515,502],{"class":118},[105,517,421],{"class":420},[105,519,470],{"class":122},[105,521,523],{"class":107,"line":522},12,[105,524,525],{"class":122},"  }\n",[105,527,529,532],{"class":107,"line":528},13,[105,530,531],{"class":118},"  .thumb",[105,533,123],{"class":122},[105,535,537,540,542,545,548,550,553,555,557,559,562,564,567],{"class":107,"line":536},14,[105,538,539],{"class":118},"    width",[105,541,397],{"class":122},[105,543,544],{"class":118},"100",[105,546,547],{"class":420},"%",[105,549,409],{"class":122},[105,551,552],{"class":118},"aspect-ratio",[105,554,397],{"class":122},[105,556,502],{"class":118},[105,558,409],{"class":122},[105,560,561],{"class":118},"object-fit",[105,563,397],{"class":122},[105,565,566],{"class":118},"cover",[105,568,470],{"class":122},[105,570,572,575,577,580,583,585,588,590,593,595,598,600,603],{"class":107,"line":571},15,[105,573,574],{"class":118},"    border-radius",[105,576,397],{"class":122},[105,578,579],{"class":118},"10",[105,581,582],{"class":420},"px",[105,584,409],{"class":122},[105,586,587],{"class":118},"display",[105,589,397],{"class":122},[105,591,592],{"class":118},"block",[105,594,409],{"class":122},[105,596,597],{"class":118},"cursor",[105,599,397],{"class":122},[105,601,602],{"class":118},"pointer",[105,604,470],{"class":122},[105,606,608],{"class":107,"line":607},16,[105,609,525],{"class":122},[105,611,613],{"class":107,"line":612},17,[105,614,431],{"emptyLinePlaceholder":430},[105,616,618,621,623,625,627,629],{"class":107,"line":617},18,[105,619,620],{"class":118},"  .detail",[105,622,391],{"class":122},[105,624,587],{"class":118},[105,626,397],{"class":122},[105,628,184],{"class":118},[105,630,424],{"class":122},[105,632,634,636,639,642,645,647,649,651],{"class":107,"line":633},19,[105,635,620],{"class":118},[105,637,638],{"class":122},"[",[105,640,641],{"class":118},"data-open",[105,643,644],{"class":122},"] { ",[105,646,587],{"class":118},[105,648,397],{"class":122},[105,650,592],{"class":118},[105,652,424],{"class":122},[105,654,656,658,660,663,665,667,669,671],{"class":107,"line":655},20,[105,657,437],{"class":118},[105,659,638],{"class":122},[105,661,662],{"class":118},"data-hidden",[105,664,644],{"class":122},[105,666,587],{"class":118},[105,668,397],{"class":122},[105,670,184],{"class":118},[105,672,424],{"class":122},[105,674,676],{"class":107,"line":675},21,[105,677,431],{"emptyLinePlaceholder":430},[105,679,681,684],{"class":107,"line":680},22,[105,682,683],{"class":118},"  .hero",[105,685,123],{"class":122},[105,687,689,691,693,695,697,699,701,703,706,709,711,713,715,717,719],{"class":107,"line":688},23,[105,690,539],{"class":118},[105,692,397],{"class":122},[105,694,544],{"class":118},[105,696,547],{"class":420},[105,698,409],{"class":122},[105,700,552],{"class":118},[105,702,397],{"class":122},[105,704,705],{"class":118},"16",[105,707,708],{"class":122}," \u002F ",[105,710,267],{"class":118},[105,712,409],{"class":122},[105,714,561],{"class":118},[105,716,397],{"class":122},[105,718,566],{"class":118},[105,720,470],{"class":122},[105,722,724,726,728,731,733,735,737,739,741],{"class":107,"line":723},24,[105,725,574],{"class":118},[105,727,397],{"class":122},[105,729,730],{"class":118},"14",[105,732,582],{"class":420},[105,734,409],{"class":122},[105,736,587],{"class":118},[105,738,397],{"class":122},[105,740,592],{"class":118},[105,742,470],{"class":122},[105,744,746],{"class":107,"line":745},25,[105,747,525],{"class":122},[105,749,751],{"class":107,"line":750},26,[105,752,431],{"emptyLinePlaceholder":430},[105,754,756],{"class":107,"line":755},27,[105,757,758],{"class":111},"  \u002F* The name is set from script on exactly one element at a time, so no\n",[105,760,762],{"class":107,"line":761},28,[105,763,764],{"class":111},"     stylesheet rule assigns it. See the toggle() function below. *\u002F\n",[105,766,768],{"class":107,"line":767},29,[105,769,431],{"emptyLinePlaceholder":430},[105,771,773],{"class":107,"line":772},30,[105,774,775],{"class":111},"  \u002F* Both captures are replaced elements. Without cover, the square\n",[105,777,779],{"class":107,"line":778},31,[105,780,781],{"class":111},"     thumbnail capture is stretched into the 16:9 hero box and the\n",[105,783,785],{"class":107,"line":784},32,[105,786,787],{"class":111},"     content visibly distorts mid-morph. *\u002F\n",[105,789,791,794,797],{"class":107,"line":790},33,[105,792,793],{"class":122},"  ::view-transition-old(",[105,795,796],{"class":306},"hero-shot",[105,798,799],{"class":122},"),\n",[105,801,803,806,808],{"class":107,"line":802},34,[105,804,805],{"class":122},"  ::view-transition-new(",[105,807,796],{"class":306},[105,809,810],{"class":122},") {\n",[105,812,814,817,819,821],{"class":107,"line":813},35,[105,815,816],{"class":118},"    object-fit",[105,818,397],{"class":122},[105,820,566],{"class":118},[105,822,470],{"class":122},[105,824,826],{"class":107,"line":825},36,[105,827,828],{"class":111},"    \u002F* Hold the incoming image fully opaque so the morph reads as one\n",[105,830,832],{"class":107,"line":831},37,[105,833,834],{"class":111},"       object changing shape rather than two images cross-fading. *\u002F\n",[105,836,838,841,843,846],{"class":107,"line":837},38,[105,839,840],{"class":118},"    mix-blend-mode",[105,842,397],{"class":122},[105,844,845],{"class":118},"normal",[105,847,470],{"class":122},[105,849,851],{"class":107,"line":850},39,[105,852,525],{"class":122},[105,854,856,858,860,863,866,868,870,872,875,877,879],{"class":107,"line":855},40,[105,857,793],{"class":122},[105,859,796],{"class":306},[105,861,862],{"class":122},") { ",[105,864,865],{"class":118},"animation",[105,867,397],{"class":122},[105,869,184],{"class":118},[105,871,409],{"class":122},[105,873,874],{"class":118},"opacity",[105,876,397],{"class":122},[105,878,458],{"class":118},[105,880,424],{"class":122},[105,882,884,886,888,890,892,894,896,898,900,902,904],{"class":107,"line":883},41,[105,885,805],{"class":122},[105,887,796],{"class":306},[105,889,862],{"class":122},[105,891,865],{"class":118},[105,893,397],{"class":122},[105,895,184],{"class":118},[105,897,409],{"class":122},[105,899,874],{"class":118},[105,901,397],{"class":122},[105,903,502],{"class":118},[105,905,424],{"class":122},[105,907,909],{"class":107,"line":908},42,[105,910,431],{"emptyLinePlaceholder":430},[105,912,914],{"class":107,"line":913},43,[105,915,916],{"class":111},"  \u002F* The group is what travels and resizes. Give it a longer, softer\n",[105,918,920],{"class":107,"line":919},44,[105,921,922],{"class":111},"     curve than the default so the distance is legible. *\u002F\n",[105,924,926,929,931],{"class":107,"line":925},45,[105,927,928],{"class":122},"  ::view-transition-group(",[105,930,796],{"class":306},[105,932,810],{"class":122},[105,934,936,939,941,944,947],{"class":107,"line":935},46,[105,937,938],{"class":118},"    animation-duration",[105,940,397],{"class":122},[105,942,943],{"class":118},"420",[105,945,946],{"class":420},"ms",[105,948,470],{"class":122},[105,950,952,955,957,960,962,965,967,970,972,974,976,978],{"class":107,"line":951},47,[105,953,954],{"class":118},"    animation-timing-function",[105,956,397],{"class":122},[105,958,959],{"class":118},"cubic-bezier",[105,961,494],{"class":122},[105,963,964],{"class":118},"0.32",[105,966,403],{"class":122},[105,968,969],{"class":118},"0.72",[105,971,403],{"class":122},[105,973,458],{"class":118},[105,975,403],{"class":122},[105,977,502],{"class":118},[105,979,980],{"class":122},");\n",[105,982,984],{"class":107,"line":983},48,[105,985,525],{"class":122},[105,987,989,992,994],{"class":107,"line":988},49,[105,990,991],{"class":122},"\u003C\u002F",[105,993,380],{"class":306},[105,995,313],{"class":122},[105,997,999,1001,1003],{"class":107,"line":998},50,[105,1000,991],{"class":122},[105,1002,339],{"class":306},[105,1004,313],{"class":122},[105,1006,1008,1010,1013],{"class":107,"line":1007},51,[105,1009,318],{"class":122},[105,1011,1012],{"class":306},"body",[105,1014,313],{"class":122},[105,1016,1018],{"class":107,"line":1017},52,[105,1019,431],{"emptyLinePlaceholder":430},[105,1021,1023,1025,1028,1031,1033,1036,1039,1041,1043],{"class":107,"line":1022},53,[105,1024,318],{"class":122},[105,1026,1027],{"class":306},"ul",[105,1029,1030],{"class":118}," class",[105,1032,326],{"class":122},[105,1034,1035],{"class":329},"\"grid\"",[105,1037,1038],{"class":118}," id",[105,1040,326],{"class":122},[105,1042,1035],{"class":329},[105,1044,313],{"class":122},[105,1046,1048,1051,1054,1057,1059,1061,1063,1066,1069,1071,1074,1077,1079,1082,1085,1087,1090,1093,1095],{"class":107,"line":1047},54,[105,1049,1050],{"class":122},"  \u003C",[105,1052,1053],{"class":306},"li",[105,1055,1056],{"class":122},">\u003C",[105,1058,146],{"class":306},[105,1060,1030],{"class":118},[105,1062,326],{"class":122},[105,1064,1065],{"class":329},"\"thumb\"",[105,1067,1068],{"class":118}," data-id",[105,1070,326],{"class":122},[105,1072,1073],{"class":329},"\"7\"",[105,1075,1076],{"class":118},"  src",[105,1078,326],{"class":122},[105,1080,1081],{"class":329},"\"\u002Fimg\u002F7.jpg\"",[105,1083,1084],{"class":118},"  alt",[105,1086,326],{"class":122},[105,1088,1089],{"class":329},"\"Coastal path\"",[105,1091,1092],{"class":122},">\u003C\u002F",[105,1094,1053],{"class":306},[105,1096,313],{"class":122},[105,1098,1100,1102,1104,1106,1108,1110,1112,1114,1116,1118,1121,1124,1126,1129,1132,1134,1137,1139,1141],{"class":107,"line":1099},55,[105,1101,1050],{"class":122},[105,1103,1053],{"class":306},[105,1105,1056],{"class":122},[105,1107,146],{"class":306},[105,1109,1030],{"class":118},[105,1111,326],{"class":122},[105,1113,1065],{"class":329},[105,1115,1068],{"class":118},[105,1117,326],{"class":122},[105,1119,1120],{"class":329},"\"12\"",[105,1122,1123],{"class":118}," src",[105,1125,326],{"class":122},[105,1127,1128],{"class":329},"\"\u002Fimg\u002F12.jpg\"",[105,1130,1131],{"class":118}," alt",[105,1133,326],{"class":122},[105,1135,1136],{"class":329},"\"Harbour at dusk\"",[105,1138,1092],{"class":122},[105,1140,1053],{"class":306},[105,1142,313],{"class":122},[105,1144,1146,1148,1150,1152,1154,1156,1158,1160,1162,1164,1167,1169,1171,1174,1176,1178,1181,1183,1185],{"class":107,"line":1145},56,[105,1147,1050],{"class":122},[105,1149,1053],{"class":306},[105,1151,1056],{"class":122},[105,1153,146],{"class":306},[105,1155,1030],{"class":118},[105,1157,326],{"class":122},[105,1159,1065],{"class":329},[105,1161,1068],{"class":118},[105,1163,326],{"class":122},[105,1165,1166],{"class":329},"\"19\"",[105,1168,1123],{"class":118},[105,1170,326],{"class":122},[105,1172,1173],{"class":329},"\"\u002Fimg\u002F19.jpg\"",[105,1175,1131],{"class":118},[105,1177,326],{"class":122},[105,1179,1180],{"class":329},"\"Pine ridge\"",[105,1182,1092],{"class":122},[105,1184,1053],{"class":306},[105,1186,313],{"class":122},[105,1188,1190,1192,1194],{"class":107,"line":1189},57,[105,1191,991],{"class":122},[105,1193,1027],{"class":306},[105,1195,313],{"class":122},[105,1197,1199],{"class":107,"line":1198},58,[105,1200,431],{"emptyLinePlaceholder":430},[105,1202,1204,1206,1209,1211,1213,1216,1218,1220,1222,1225,1227,1230],{"class":107,"line":1203},59,[105,1205,318],{"class":122},[105,1207,1208],{"class":306},"section",[105,1210,1030],{"class":118},[105,1212,326],{"class":122},[105,1214,1215],{"class":329},"\"detail\"",[105,1217,1038],{"class":118},[105,1219,326],{"class":122},[105,1221,1215],{"class":329},[105,1223,1224],{"class":118}," tabindex",[105,1226,326],{"class":122},[105,1228,1229],{"class":329},"\"-1\"",[105,1231,313],{"class":122},[105,1233,1235,1237,1239,1241,1243,1246,1248,1250,1252,1254,1256,1259,1261,1263,1265],{"class":107,"line":1234},60,[105,1236,1050],{"class":122},[105,1238,146],{"class":306},[105,1240,1030],{"class":118},[105,1242,326],{"class":122},[105,1244,1245],{"class":329},"\"hero\"",[105,1247,1038],{"class":118},[105,1249,326],{"class":122},[105,1251,1245],{"class":329},[105,1253,1123],{"class":118},[105,1255,326],{"class":122},[105,1257,1258],{"class":329},"\"\"",[105,1260,1131],{"class":118},[105,1262,326],{"class":122},[105,1264,1258],{"class":329},[105,1266,313],{"class":122},[105,1268,1270,1272,1274,1276,1278,1281,1283,1285],{"class":107,"line":1269},61,[105,1271,1050],{"class":122},[105,1273,10],{"class":306},[105,1275,1038],{"class":118},[105,1277,326],{"class":122},[105,1279,1280],{"class":329},"\"heroTitle\"",[105,1282,1092],{"class":122},[105,1284,10],{"class":306},[105,1286,313],{"class":122},[105,1288,1290,1292,1295,1298,1300,1303,1305,1307,1310,1313,1315],{"class":107,"line":1289},62,[105,1291,1050],{"class":122},[105,1293,1294],{"class":306},"button",[105,1296,1297],{"class":118}," type",[105,1299,326],{"class":122},[105,1301,1302],{"class":329},"\"button\"",[105,1304,1038],{"class":118},[105,1306,326],{"class":122},[105,1308,1309],{"class":329},"\"back\"",[105,1311,1312],{"class":122},">Back to grid\u003C\u002F",[105,1314,1294],{"class":306},[105,1316,313],{"class":122},[105,1318,1320,1322,1324],{"class":107,"line":1319},63,[105,1321,991],{"class":122},[105,1323,1208],{"class":306},[105,1325,313],{"class":122},[105,1327,1329],{"class":107,"line":1328},64,[105,1330,431],{"emptyLinePlaceholder":430},[105,1332,1334,1336,1339],{"class":107,"line":1333},65,[105,1335,318],{"class":122},[105,1337,1338],{"class":306},"script",[105,1340,313],{"class":122},[105,1342,1344,1347,1350,1353,1356,1360,1362,1365],{"class":107,"line":1343},66,[105,1345,1346],{"class":420},"  const",[105,1348,1349],{"class":118}," grid",[105,1351,1352],{"class":420}," =",[105,1354,1355],{"class":122}," document.",[105,1357,1359],{"class":1358},"sKwhi","getElementById",[105,1361,494],{"class":122},[105,1363,1364],{"class":329},"'grid'",[105,1366,980],{"class":122},[105,1368,1370,1372,1375,1377,1379,1381,1383,1386],{"class":107,"line":1369},67,[105,1371,1346],{"class":420},[105,1373,1374],{"class":118}," detail",[105,1376,1352],{"class":420},[105,1378,1355],{"class":122},[105,1380,1359],{"class":1358},[105,1382,494],{"class":122},[105,1384,1385],{"class":329},"'detail'",[105,1387,980],{"class":122},[105,1389,1391,1393,1396,1398,1400,1402,1404,1407],{"class":107,"line":1390},68,[105,1392,1346],{"class":420},[105,1394,1395],{"class":118}," hero",[105,1397,1352],{"class":420},[105,1399,1355],{"class":122},[105,1401,1359],{"class":1358},[105,1403,494],{"class":122},[105,1405,1406],{"class":329},"'hero'",[105,1408,980],{"class":122},[105,1410,1412,1414,1417,1419,1421,1423,1425,1428],{"class":107,"line":1411},69,[105,1413,1346],{"class":420},[105,1415,1416],{"class":118}," title",[105,1418,1352],{"class":420},[105,1420,1355],{"class":122},[105,1422,1359],{"class":1358},[105,1424,494],{"class":122},[105,1426,1427],{"class":329},"'heroTitle'",[105,1429,980],{"class":122},[105,1431,1433,1436,1439,1441,1444],{"class":107,"line":1432},70,[105,1434,1435],{"class":420},"  let",[105,1437,1438],{"class":122}," active ",[105,1440,326],{"class":420},[105,1442,1443],{"class":118}," null",[105,1445,470],{"class":122},[105,1447,1449],{"class":107,"line":1448},71,[105,1450,431],{"emptyLinePlaceholder":430},[105,1452,1454,1457,1460,1462,1465],{"class":107,"line":1453},72,[105,1455,1456],{"class":420},"  function",[105,1458,1459],{"class":1358}," open",[105,1461,494],{"class":122},[105,1463,146],{"class":1464},"soyes",[105,1466,810],{"class":122},[105,1468,1470,1473,1475],{"class":107,"line":1469},73,[105,1471,1472],{"class":122},"    active ",[105,1474,326],{"class":420},[105,1476,1477],{"class":122}," img;\n",[105,1479,1481],{"class":107,"line":1480},74,[105,1482,1483],{"class":111},"    \u002F\u002F Assign the shared identity to exactly two elements, one per capture.\n",[105,1485,1487,1490,1492,1495],{"class":107,"line":1486},75,[105,1488,1489],{"class":122},"    img.style.viewTransitionName ",[105,1491,326],{"class":420},[105,1493,1494],{"class":329}," 'hero-shot'",[105,1496,470],{"class":122},[105,1498,1500,1503,1505,1507],{"class":107,"line":1499},76,[105,1501,1502],{"class":122},"    hero.style.viewTransitionName ",[105,1504,326],{"class":420},[105,1506,1494],{"class":329},[105,1508,470],{"class":122},[105,1510,1512,1515,1517],{"class":107,"line":1511},77,[105,1513,1514],{"class":122},"    hero.src ",[105,1516,326],{"class":420},[105,1518,1519],{"class":122}," img.src;\n",[105,1521,1523,1526,1528],{"class":107,"line":1522},78,[105,1524,1525],{"class":122},"    hero.alt ",[105,1527,326],{"class":420},[105,1529,1530],{"class":122}," img.alt;\n",[105,1532,1534,1537,1539],{"class":107,"line":1533},79,[105,1535,1536],{"class":122},"    title.textContent ",[105,1538,326],{"class":420},[105,1540,1530],{"class":122},[105,1542,1544,1547,1550,1552,1555,1557,1560],{"class":107,"line":1543},80,[105,1545,1546],{"class":122},"    grid.",[105,1548,1549],{"class":1358},"setAttribute",[105,1551,494],{"class":122},[105,1553,1554],{"class":329},"'data-hidden'",[105,1556,403],{"class":122},[105,1558,1559],{"class":329},"''",[105,1561,980],{"class":122},[105,1563,1565,1568,1570,1572,1575,1577,1579],{"class":107,"line":1564},81,[105,1566,1567],{"class":122},"    detail.",[105,1569,1549],{"class":1358},[105,1571,494],{"class":122},[105,1573,1574],{"class":329},"'data-open'",[105,1576,403],{"class":122},[105,1578,1559],{"class":329},[105,1580,980],{"class":122},[105,1582,1584],{"class":107,"line":1583},82,[105,1585,525],{"class":122},[105,1587,1589],{"class":107,"line":1588},83,[105,1590,431],{"emptyLinePlaceholder":430},[105,1592,1594,1596,1599],{"class":107,"line":1593},84,[105,1595,1456],{"class":420},[105,1597,1598],{"class":1358}," close",[105,1600,1601],{"class":122},"() {\n",[105,1603,1605,1607,1610,1612,1614],{"class":107,"line":1604},85,[105,1606,1546],{"class":122},[105,1608,1609],{"class":1358},"removeAttribute",[105,1611,494],{"class":122},[105,1613,1554],{"class":329},[105,1615,980],{"class":122},[105,1617,1619,1621,1623,1625,1627],{"class":107,"line":1618},86,[105,1620,1567],{"class":122},[105,1622,1609],{"class":1358},[105,1624,494],{"class":122},[105,1626,1574],{"class":329},[105,1628,980],{"class":122},[105,1630,1632],{"class":107,"line":1631},87,[105,1633,525],{"class":122},[105,1635,1637],{"class":107,"line":1636},88,[105,1638,431],{"emptyLinePlaceholder":430},[105,1640,1642,1644,1647,1649,1652],{"class":107,"line":1641},89,[105,1643,1456],{"class":420},[105,1645,1646],{"class":1358}," run",[105,1648,494],{"class":122},[105,1650,1651],{"class":1464},"fn",[105,1653,810],{"class":122},[105,1655,1657,1660,1663,1666,1669,1671,1674,1677],{"class":107,"line":1656},90,[105,1658,1659],{"class":420},"    if",[105,1661,1662],{"class":122}," (",[105,1664,1665],{"class":420},"!",[105,1667,1668],{"class":122},"document.startViewTransition) { ",[105,1670,1651],{"class":1358},[105,1672,1673],{"class":122},"(); ",[105,1675,1676],{"class":420},"return",[105,1678,424],{"class":122},[105,1680,1682],{"class":107,"line":1681},91,[105,1683,1684],{"class":111},"    \u002F\u002F finished resolves once the overlay is torn down; clear names then so\n",[105,1686,1688],{"class":107,"line":1687},92,[105,1689,1690],{"class":111},"    \u002F\u002F the next open() never finds two elements holding hero-shot.\n",[105,1692,1694,1697,1700,1703,1706,1709,1712],{"class":107,"line":1693},93,[105,1695,1696],{"class":122},"    document.",[105,1698,1699],{"class":1358},"startViewTransition",[105,1701,1702],{"class":122},"(fn).finished.",[105,1704,1705],{"class":1358},"then",[105,1707,1708],{"class":122},"(() ",[105,1710,1711],{"class":420},"=>",[105,1713,123],{"class":122},[105,1715,1717,1720,1723,1725,1728],{"class":107,"line":1716},94,[105,1718,1719],{"class":420},"      if",[105,1721,1722],{"class":122}," (active) active.style.viewTransitionName ",[105,1724,326],{"class":420},[105,1726,1727],{"class":329}," ''",[105,1729,470],{"class":122},[105,1731,1733,1736,1738,1740],{"class":107,"line":1732},95,[105,1734,1735],{"class":122},"      hero.style.viewTransitionName ",[105,1737,326],{"class":420},[105,1739,1727],{"class":329},[105,1741,470],{"class":122},[105,1743,1745],{"class":107,"line":1744},96,[105,1746,1747],{"class":122},"    });\n",[105,1749,1751],{"class":107,"line":1750},97,[105,1752,525],{"class":122},[105,1754,1756],{"class":107,"line":1755},98,[105,1757,431],{"emptyLinePlaceholder":430},[105,1759,1761,1764,1767,1769,1772,1774,1777,1780],{"class":107,"line":1760},99,[105,1762,1763],{"class":122},"  grid.",[105,1765,1766],{"class":1358},"addEventListener",[105,1768,494],{"class":122},[105,1770,1771],{"class":329},"'click'",[105,1773,403],{"class":122},[105,1775,1776],{"class":1464},"e",[105,1778,1779],{"class":420}," =>",[105,1781,123],{"class":122},[105,1783,1785,1788,1791,1793,1796,1799,1801,1804],{"class":107,"line":1784},100,[105,1786,1787],{"class":420},"    const",[105,1789,1790],{"class":118}," img",[105,1792,1352],{"class":420},[105,1794,1795],{"class":122}," e.target.",[105,1797,1798],{"class":1358},"closest",[105,1800,494],{"class":122},[105,1802,1803],{"class":329},"'.thumb'",[105,1805,980],{"class":122},[105,1807,1809,1811,1814,1817,1819,1821,1823,1826,1829,1832],{"class":107,"line":1808},101,[105,1810,1659],{"class":420},[105,1812,1813],{"class":122}," (img) ",[105,1815,1816],{"class":1358},"run",[105,1818,1708],{"class":122},[105,1820,1711],{"class":420},[105,1822,391],{"class":122},[105,1824,1825],{"class":1358},"open",[105,1827,1828],{"class":122},"(img); detail.",[105,1830,1831],{"class":1358},"focus",[105,1833,1834],{"class":122},"(); });\n",[105,1836,1838],{"class":107,"line":1837},102,[105,1839,1840],{"class":122},"  });\n",[105,1842,1844],{"class":107,"line":1843},103,[105,1845,431],{"emptyLinePlaceholder":430},[105,1847,1849,1852,1854,1856,1859,1862,1864,1866,1868,1871,1873],{"class":107,"line":1848},104,[105,1850,1851],{"class":122},"  document.",[105,1853,1359],{"class":1358},[105,1855,494],{"class":122},[105,1857,1858],{"class":329},"'back'",[105,1860,1861],{"class":122},").",[105,1863,1766],{"class":1358},[105,1865,494],{"class":122},[105,1867,1771],{"class":329},[105,1869,1870],{"class":122},", () ",[105,1872,1711],{"class":420},[105,1874,123],{"class":122},[105,1876,1878,1880,1882,1884,1886],{"class":107,"line":1877},105,[105,1879,1659],{"class":420},[105,1881,1722],{"class":122},[105,1883,326],{"class":420},[105,1885,1494],{"class":329},[105,1887,470],{"class":122},[105,1889,1891,1893,1895,1897],{"class":107,"line":1890},106,[105,1892,1502],{"class":122},[105,1894,326],{"class":420},[105,1896,1494],{"class":329},[105,1898,470],{"class":122},[105,1900,1902,1905],{"class":107,"line":1901},107,[105,1903,1904],{"class":1358},"    run",[105,1906,1907],{"class":122},"(close);\n",[105,1909,1911],{"class":107,"line":1910},108,[105,1912,1840],{"class":122},[105,1914,1916,1918,1920],{"class":107,"line":1915},109,[105,1917,991],{"class":122},[105,1919,1338],{"class":306},[105,1921,313],{"class":122},[105,1923,1925],{"class":107,"line":1924},110,[105,1926,431],{"emptyLinePlaceholder":430},[105,1928,1930,1932,1934],{"class":107,"line":1929},111,[105,1931,991],{"class":122},[105,1933,1012],{"class":306},[105,1935,313],{"class":122},[105,1937,1939,1941,1943],{"class":107,"line":1938},112,[105,1940,991],{"class":122},[105,1942,296],{"class":306},[105,1944,313],{"class":122},[14,1946,1947,1948,1951],{},"Note ",[18,1949,1950],{},"detail.focus()"," inside the callback. The overlay is inert, so without an explicit focus move the keyboard user is left on a button that no longer exists.",[32,1953],{},[35,1955,1957],{"id":1956},"the-key-technique-the-group-does-the-moving","The key technique: the group does the moving",[14,1959,1960,1961,1964,1965,1968,1969,403,1972,1975,1976,1979],{},"It is tempting to write ",[18,1962,1963],{},"@keyframes"," that translate and scale the snapshots. Do not. ",[18,1966,1967],{},"::view-transition-group()"," already carries an animation the browser generated from the two measured rectangles, interpolating ",[18,1970,1971],{},"width",[18,1973,1974],{},"height",", and ",[18,1977,1978],{},"transform"," from the thumbnail's box to the hero's box. It knows the exact numbers; you do not, and cannot without measuring.",[14,1981,1982,1983,1987,1988,1991],{},"Your job is only to stop the ",[1984,1985,1986],"em",{},"snapshots inside that group"," from fighting it. That is what the two ",[18,1989,1990],{},"animation: none"," declarations in the implementation do: they cancel the default cross-fade so the new image is simply opaque for the whole morph, while the group carries it across the screen. The result reads as one object changing shape instead of two pictures dissolving into each other during a move — which is the difference between a native-feeling morph and a muddy blur.",[14,1993,1994,1995,1997,1998,2001,2002,2004,2005,2009],{},"The complementary detail is ",[18,1996,561],{},". Because the two captures have different aspect ratios (a square thumbnail, a 16:9 hero) the default ",[18,1999,2000],{},"fill"," stretches the square capture into the wide box. ",[18,2003,566],{}," keeps the framing honest throughout. If your source images are already the right shape, the same discipline is worth applying at the layout level with ",[23,2006,2008],{"href":2007},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media\u002F","aspect-ratio for responsive media",".",[32,2011],{},[35,2013,2015],{"id":2014},"variation-naming-from-data-with-generated-idents","Variation: naming from data with generated idents",[14,2017,2018],{},"Assigning names from script is explicit and easy to reason about, but for a static list rendered on the server you can bake unique idents in and skip the assignment step entirely:",[96,2020,2022],{"className":98,"code":2021,"language":100,"meta":101,"style":101},"\u002F* Server-rendered: each card carries --vt-id: 7, 12, 19… as an inline style. *\u002F\n.card {\n  view-transition-name: var(--vt-name, none);\n}\n",[18,2023,2024,2029,2036,2056],{"__ignoreMap":101},[105,2025,2026],{"class":107,"line":108},[105,2027,2028],{"class":111},"\u002F* Server-rendered: each card carries --vt-id: 7, 12, 19… as an inline style. *\u002F\n",[105,2030,2031,2034],{"class":107,"line":115},[105,2032,2033],{"class":118},".card",[105,2035,123],{"class":122},[105,2037,2038,2040,2042,2045,2047,2050,2052,2054],{"class":107,"line":126},[105,2039,129],{"class":118},[105,2041,397],{"class":122},[105,2043,2044],{"class":118},"var",[105,2046,494],{"class":122},[105,2048,2049],{"class":1464},"--vt-name",[105,2051,403],{"class":122},[105,2053,184],{"class":118},[105,2055,980],{"class":122},[105,2057,2058],{"class":107,"line":135},[105,2059,138],{"class":122},[14,2061,2062,2063,2066],{},"The template writes ",[18,2064,2065],{},"style=\"--vt-name: card-7\""," on each element. Uniqueness is now guaranteed by the data rather than by careful scripting, and the CSS stays declarative. The catch is that every visible card is then named, which means one snapshot texture per card — acceptable for a dozen, wasteful for a hundred. When the list is long, prefer the assign-on-demand approach and let the rest of the grid travel inside the root snapshot.",[14,2068,2069,2070,2073,2074,2009],{},"A newer alternative is ",[18,2071,2072],{},"view-transition-name: match-element",", which asks the engine to derive a stable per-element identity so you never invent idents at all. It solves this problem cleanly where it exists, but its availability is much narrower than the rest of the API in mid-2026, so treat it as an enhancement over one of the two patterns above rather than a replacement for them. This is the same kind of value-level indirection used for motion tokens in ",[23,2075,2077],{"href":2076},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations\u002F","fluid spacing tokens driving transition durations",[32,2079],{},[35,2081,2083],{"id":2082},"browser-support-note","Browser support note",[14,2085,2086,2088,2089,2092],{},[18,2087,20],{}," ships with same-document view transitions: Chrome and Edge 111+, Safari 18+, and Firefox 144+ — every current engine. In any older browser the property is unknown and dropped at parse time with no effect on surrounding rules, and the click handler's feature test means the detail view still opens, just instantly. ",[18,2090,2091],{},"view-transition-class",", the convenience for styling many names with one selector, is narrower and available in Chromium at the time of writing, so write the per-name selectors when broad coverage matters.",[32,2094],{},[35,2096,2098],{"id":2097},"faq","FAQ",[14,2100,2101,2104,2105,2107],{},[88,2102,2103],{},"Why does my transition do nothing when several cards are visible?","\nTwo elements almost certainly share one ",[18,2106,20],{}," in the same capture. That is invalid, and rather than picking a winner the browser skips the entire transition, so nothing animates at all.",[14,2109,2110,2113,2114,2116,2117,2120],{},[88,2111,2112],{},"Do the old and new elements have to be the same kind of element?","\nNo. The browser matches purely on the name string, not on tag, class, or position in the tree. An ",[18,2115,146],{}," can morph into a ",[18,2118,2119],{},"div"," because only the two captured rectangles and their images are compared.",[14,2122,2123,2126,2127,2130,2131,2134],{},[88,2124,2125],{},"Why does my image squash while it grows?","\nSnapshots are replaced elements and default to ",[18,2128,2129],{},"object-fit: fill",", so a capture with one aspect ratio is stretched into a box with another. Set ",[18,2132,2133],{},"object-fit: cover"," on both the old and new pseudo-elements.",[14,2136,2137,2140],{},[88,2138,2139],{},"Should every card in a list have a view-transition-name?","\nOnly if every card needs to animate independently. Each name costs an extra snapshot texture, so name the element the user is acting on and let everything else travel with the root snapshot.",[32,2142],{},[35,2144,2146],{"id":2145},"related","Related",[1027,2148,2149,2154,2161,2168,2174],{},[1053,2150,2151,2153],{},[23,2152,26],{"href":25}," — the parent guide on snapshots and the pseudo-element tree.",[1053,2155,2156,2160],{},[23,2157,2159],{"href":2158},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fsame-document-view-transitions\u002F","Same-document view transitions"," — writing custom keyframes on the old and new snapshots.",[1053,2162,2163,2167],{},[23,2164,2166],{"href":2165},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion\u002F","View transitions with reduced motion"," — what a morph should become when the user asks for less movement.",[1053,2169,2170,2173],{},[23,2171,2172],{"href":2007},"Aspect-ratio for responsive media"," — keeping thumbnail and hero framing consistent before the morph starts.",[1053,2175,2176,2180],{},[23,2177,2179],{"href":2178},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties\u002F","Staggered list animations with custom properties"," — per-item identity driving motion, without the snapshot machinery.",[380,2182,2183],{},"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 .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}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 .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}",{"title":101,"searchDepth":115,"depth":115,"links":2185},[2186,2187,2188,2189,2190,2191,2192,2193],{"id":37,"depth":115,"text":38},{"id":79,"depth":115,"text":80},{"id":287,"depth":115,"text":288},{"id":1956,"depth":115,"text":1957},{"id":2014,"depth":115,"text":2015},{"id":2082,"depth":115,"text":2083},{"id":2097,"depth":115,"text":2098},{"id":2145,"depth":115,"text":2146},"Use view-transition-name to morph a thumbnail into a hero image, and work around the rule that every name must be unique within a single snapshot capture.","md",{"pageTitle":2197,"datePublished":2198,"dateModified":2198,"faq":2199},"view-transition-name & Shared Elements","2026-07-20",[2200,2202,2204,2206],{"q":2103,"a":2201},"Two elements almost certainly share one view-transition-name in the same capture. That is invalid, and rather than picking a winner the browser skips the entire transition, so nothing animates at all.",{"q":2112,"a":2203},"No. The browser matches purely on the name string, not on tag, class, or position in the tree. An img can morph into a div because only the two captured rectangles and their images are compared.",{"q":2125,"a":2205},"Snapshots are replaced elements and default to object-fit: fill, so a capture with one aspect ratio is stretched into a box with another. Set object-fit: cover on both the old and new pseudo-elements.",{"q":2139,"a":2207},"Only if every card needs to animate independently. Each name costs an extra snapshot texture, so name the element the user is acting on and let everything else travel with the root snapshot.","\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-names-shared-elements",{"title":5,"description":2194},"css-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transition-names-shared-elements\u002Findex","0wRUOLAAySpnrGh4ENWYhAuW8GGJafdI3cqW2u4X6no",[2213,2216,2219,2222,2225,2228,2231,2234,2237,2240,2243,2246,2249,2252,2255,2258,2261,2264,2267,2270,2273,2276,2279,2282,2285,2288,2291,2294,2297,2300,2303,2306,2309,2312,2315,2318,2321,2324,2327,2330,2333,2336,2339,2342,2345,2346,2349,2352,2355,2358,2361,2364,2367,2370,2373,2376,2379,2382,2385,2388,2391,2394,2397,2400,2403,2406,2409,2412,2415,2418,2421,2424,2427,2430,2433,2436,2439,2442,2445,2448,2451,2454,2457,2460,2463,2466,2469,2472],{"path":2214,"title":2215},"\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":2217,"title":2218},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations","Accessibility in CSS Animations: Patterns, Specs & Best Practices",{"path":2220,"title":2221},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fprefers-reduced-motion-recipes","prefers-reduced-motion Recipes: A Reduction for Every Common Effect",{"path":2223,"title":2224},"\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":2226,"title":2227},"\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":2229,"title":2230},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fvestibular-safe-animation-patterns","Vestibular-Safe Animation Patterns: Why Some Motion Makes People Sick",{"path":2232,"title":2233},"\u002Fcss-only-micro-interactions-animations\u002Faccessibility-in-css-animations\u002Fwcag-motion-success-criteria","WCAG Motion Success Criteria: What Each One Actually Requires",{"path":2235,"title":2236},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fcontainer-query-hover-affordances","Container Query Hover Affordances: When Narrow Means Persistent, Not Hidden",{"path":2238,"title":2239},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion","Container-Aware Motion: Animation Sized by the Space a Component Actually Has",{"path":2241,"title":2242},"\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":2244,"title":2245},"\u002Fcss-only-micro-interactions-animations\u002Fcontainer-aware-motion\u002Fsuppressing-motion-in-small-containers","Suppressing Motion in Small Containers: Deliberately Animating Nothing",{"path":2247,"title":2248},"\u002Fcss-only-micro-interactions-animations\u002Fcss-animation-vs-web-animations-api","CSS Animation vs the Web Animations API: A Decision Guide",{"path":2250,"title":2251},"\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":2253,"title":2254},"\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":2256,"title":2257},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture\u002Ffluid-spacing-tokens-driving-transition-durations","Fluid Spacing Tokens That Drive Transition Durations",{"path":2259,"title":2260},"\u002Fcss-only-micro-interactions-animations\u002Fcss-custom-properties-architecture","CSS Custom Properties Architecture: Scalable Design Systems & Dynamic UI",{"path":2262,"title":2263},"\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":2265,"title":2266},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fcss-transition-timing-functions","CSS Transition Timing Functions: ease, cubic-bezier(), steps() and linear()",{"path":2268,"title":2269},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals","CSS Transition Fundamentals: Architecture, Performance & Patterns",{"path":2271,"title":2272},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Fstarting-style-entry-animations","@starting-style: Animating an Element's Very First Style Change",{"path":2274,"title":2275},"\u002Fcss-only-micro-interactions-animations\u002Fcss-transition-fundamentals\u002Ftransitioning-display-with-allow-discrete","Transitioning display with transition-behavior: allow-discrete and @starting-style",{"path":2277,"title":2278},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Faccessible-css-only-tooltips","Accessible CSS-Only Tooltips and Hover Cards With  and ",{"path":2280,"title":2281},"\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":2283,"title":2284},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design\u002Ffocus-within-form-patterns"," Form Patterns: Styling a Group From the Field Inside It",{"path":2286,"title":2287},"\u002Fcss-only-micro-interactions-animations\u002Fhover-focus-state-design","Hover & Focus State Design: Spec-Compliant Patterns for Modern UIs",{"path":2289,"title":2290},"\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":2292,"title":2293},"\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":2295,"title":2296},"\u002Fcss-only-micro-interactions-animations","CSS-Only Micro-Interactions & Animations: Architecture, Performance & Implementation",{"path":2298,"title":2299},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcontainer-query-triggered-keyframe-animations","Container-Query-Triggered Keyframe Animations: Animate Differently per Available Space",{"path":2301,"title":2302},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fcss-only-accordions-and-disclosure","CSS-Only Accordions and Disclosure Widgets with details and summary",{"path":2304,"title":2305},"\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":2307,"title":2308},"\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":2310,"title":2311},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns","Keyframe Animation Patterns: Spec-Compliant Architectures for Modern UIs",{"path":2313,"title":2314},"\u002Fcss-only-micro-interactions-animations\u002Fkeyframe-animation-patterns\u002Fstaggered-list-animations-with-custom-properties","Staggered List Animations Using --i Index Custom Properties",{"path":2316,"title":2317},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration","Performance & GPU Acceleration in CSS: A Developer’s Blueprint",{"path":2319,"title":2320},"\u002Fcss-only-micro-interactions-animations\u002Fperformance-gpu-acceleration\u002Foptimizing-css-animations-for-60fps","Optimizing CSS Animations for 60fps: Budgeting the Frame",{"path":2322,"title":2323},"\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":2325,"title":2326},"\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":2328,"title":2329},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations","Scroll-Driven Animations: Binding Motion to Scroll Position in Pure CSS",{"path":2331,"title":2332},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-driven-animation-fallbacks","Shipping Scroll-Driven Animations Without Breaking Anything",{"path":2334,"title":2335},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-progress-bar-without-javascript","A Reading Progress Bar Driven by scroll(root)",{"path":2337,"title":2338},"\u002Fcss-only-micro-interactions-animations\u002Fscroll-driven-animations\u002Fscroll-triggered-reveal-animations","Reveal-on-Scroll with view() and animation-range",{"path":2340,"title":2341},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers","View Transitions for CSS Developers: the Pseudo-Element Tree, Snapshots, and Named Elements",{"path":2343,"title":2344},"\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":2208,"title":5},{"path":2347,"title":2348},"\u002Fcss-only-micro-interactions-animations\u002Fview-transitions-for-css-developers\u002Fview-transitions-with-reduced-motion","Honouring prefers-reduced-motion in View Transitions",{"path":2350,"title":2351},"\u002F","Modern CSS Layouts & Micro-Interactions",{"path":2353,"title":2354},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioned-tooltips","Anchor-Positioned Tooltips: Tethering, Flipping, and Getting the Semantics Right",{"path":2356,"title":2357},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fanchor-positioning-fallbacks","Anchor Positioning Fallbacks: A Graceful Floor for Older Browser Versions",{"path":2359,"title":2360},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays","CSS Anchor Positioning and Overlays: Tethering Elements Without JavaScript",{"path":2362,"title":2363},"\u002Fmastering-container-queries-responsive-layouts\u002Fanchor-positioning-and-overlays\u002Fpopover-attribute-and-css-styling","The popover Attribute: Top-Layer Overlays With No JavaScript",{"path":2365,"title":2366},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Ffeature-detection-with-supports","Feature Detection with @supports: Syntax, Semantics, and the Traps",{"path":2368,"title":2369},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks\u002Fhandling-container-query-fallbacks-for-older-browsers","Handling Container Query Fallbacks for Older Browsers",{"path":2371,"title":2372},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-fallbacks","Container Query Fallbacks: Spec-Compliant CSS Strategies for Legacy Browsers",{"path":2374,"title":2375},"\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":2377,"title":2378},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-type-size-vs-inline-size","Choosing container-type: inline-size, size, or normal",{"path":2380,"title":2381},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fcontainer-vs-media-queries-comparison","Container vs Media Queries: Choosing the Right Reference Box",{"path":2383,"title":2384},"\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":2386,"title":2387},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics","Container Query Syntax Basics",{"path":2389,"title":2390},"\u002Fmastering-container-queries-responsive-layouts\u002Fcontainer-query-syntax-basics\u002Fnesting-and-naming-container-queries","Nesting and Naming Container Queries: Targeting the Right Ancestor",{"path":2392,"title":2393},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fauto-fit-minmax-responsive-grids","Responsive Grids with repeat(auto-fit, minmax())",{"path":2395,"title":2396},"\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":2398,"title":2399},"\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":2401,"title":2402},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts","CSS Grid and Subgrid Layouts for Responsive Interfaces",{"path":2404,"title":2405},"\u002Fmastering-container-queries-responsive-layouts\u002Fcss-grid-and-subgrid-layouts\u002Fsubgrid-vs-nested-grid","Subgrid vs an Independently Nested Grid",{"path":2407,"title":2408},"\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":2410,"title":2411},"\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":2413,"title":2414},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-type-accessibility-and-zoom","Fluid Type, Accessibility and Zoom: The vw-Only Trap",{"path":2416,"title":2417},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp\u002Ffluid-typography-without-javascript","Fluid Typography Without JavaScript: A Precision CSS Reference",{"path":2419,"title":2420},"\u002Fmastering-container-queries-responsive-layouts\u002Ffluid-typography-with-clamp","Fluid Typography with clamp(): A Practical Guide for Modern CSS",{"path":2422,"title":2423},"\u002Fmastering-container-queries-responsive-layouts","Mastering Container Queries & Responsive Layouts",{"path":2425,"title":2426},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Faspect-ratio-for-responsive-media","Using aspect-ratio for Responsive Media and Preventing Layout Shift",{"path":2428,"title":2429},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques","Intrinsic Sizing Techniques: Modern CSS Layouts for Responsive UI",{"path":2431,"title":2432},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fmin-max-fit-content-explained","min-content, max-content, and fit-content() Explained",{"path":2434,"title":2435},"\u002Fmastering-container-queries-responsive-layouts\u002Fintrinsic-sizing-techniques\u002Fpreventing-flex-and-grid-overflow","The min-width: auto Trap in Flex and Grid Layouts",{"path":2437,"title":2438},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-for-reset-and-tokens","Cascade Layers for Reset and Design Tokens",{"path":2440,"title":2441},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies\u002Fcascade-layers-vs-specificity-hacks","Cascade Layers vs Specificity Hacks: Ordering Instead of Escalating",{"path":2443,"title":2444},"\u002Fmastering-container-queries-responsive-layouts\u002Fmodern-css-reset-strategies","Modern CSS Reset Strategies: A Spec-Compliant Foundation",{"path":2446,"title":2447},"\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":2449,"title":2450},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-data-tables","Container Query Data Tables: Reflowing Tables to Cards",{"path":2452,"title":2453},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fcontainer-query-sidebar-layouts","Container Query Sidebar Layouts That Travel Between Contexts",{"path":2455,"title":2456},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns","Responsive Component Patterns: Architecture & Implementation",{"path":2458,"title":2459},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-forms-with-container-queries","Responsive Forms with Container Queries: Reflow Without Losing the Wiring",{"path":2461,"title":2462},"\u002Fmastering-container-queries-responsive-layouts\u002Fresponsive-component-patterns\u002Fresponsive-navigation-without-media-queries","Responsive Navigation Without Media Queries Using Container Queries",{"path":2464,"title":2465},"\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":2467,"title":2468},"\u002Fmastering-container-queries-responsive-layouts\u002Fstyle-queries-and-container-state","Style Queries and Container State: Token-Driven Component Variants",{"path":2470,"title":2471},"\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":2473,"title":2474},"\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",1784566157454]