[{"data":1,"prerenderedAt":951},["ShallowReactive",2],{"content:\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance":3,"surroundings:\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance":942},{"id":4,"title":5,"body":6,"description":922,"extension":923,"meta":924,"navigation":935,"path":936,"seo":937,"stem":940,"__hash__":941},"content\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance\u002Findex.md","View Transitions API Performance",{"type":7,"value":8,"toc":904},"minimark",[9,13,37,40,188,193,225,229,235,241,247,253,257,262,392,396,399,403,410,475,479,486,543,547,554,558,574,698,702,705,709,715,719,745,749,758,764,770,776,780,792,801,810,819,828,841,853,862,866,889,894,897,900],[10,11,5],"h1",{"id":12},"view-transitions-api-performance",[14,15,16,17,22,23,27,28,32,33,36],"p",{},"This guide is part of ",[18,19,21],"a",{"href":20},"\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002F","Animation & Compositing Performance",", within ",[18,24,26],{"href":25},"\u002Frendering-css-performance\u002F","Rendering & CSS Performance",". The View Transitions API animates between two states of a page — or between two pages — with a few lines of code. For same-document transitions, ",[29,30,31],"code",{},"document.startViewTransition(callback)"," captures a snapshot of the current state, runs your callback to update the DOM, captures the new state, and animates between them with CSS. For cross-document transitions, the ",[29,34,35],{},"@view-transition { navigation: auto; }"," rule enables the same effect across same-origin navigations in supporting browsers.",[14,38,39],{},"The API is efficient in that the animation itself runs on snapshots, typically on the compositor. But the transition has costs around it: capturing snapshots requires rendering, the page is non-interactive while the transition runs, many named elements multiply snapshot work and memory, and cross-document transitions can delay the moment the new page is shown. Used carelessly, view transitions can make INP and perceived navigation speed worse.",[14,41,42],{},[43,44,50,51,50,58,50,62,50,65,50,83,50,91,50,97,50,105,50,112,50,117,50,121,50,127,50,131,50,134,50,137,50,141,50,144,50,147,50,151,50,154,50,157,50,160,50,164,50,167,50,176,50,180,50,184,50],"svg",{"viewBox":45,"width":46,"role":47,"ariaLabel":48,"style":49},"0 0 760 149","100%","img","Stages of a same-document view transition from capturing the old state to finishing the animation.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[52,53],"rect",{"className":54,"x":56,"y":56,"width":46,"height":46,"fill":57},[55],"svg-canvas","0","#ffffff",[59,60,61],"title",{},"Same-document view transition lifecycle",[63,64,48],"desc",{},[66,67,68],"defs",{},[69,70,77],"marker",{"id":71,"viewBox":72,"refX":73,"refY":74,"markerWidth":75,"markerHeight":75,"orient":76},"fa352a2d7b","0 0 10 10","9","5","7","auto-start-reverse",[78,79],"path",{"d":80,"fill":81,"style":82},"M0 0 L10 5 L0 10 z","currentColor","fill-opacity:0.7",[52,84],{"x":85,"y":85,"width":86,"height":87,"rx":88,"fill":89,"stroke":81,"style":90},"1","758","147","10","none","stroke-opacity:0.18",[92,93,61],"text",{"x":94,"y":95,"fill":81,"style":96},"28.0","34.0","font-size:16px;font-weight:700",[52,98],{"x":94,"y":99,"width":100,"height":101,"rx":102,"fill":103,"stroke":103,"style":104},"56.0","108.8","71.0","6","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[92,106,111],{"x":107,"y":108,"fill":81,"style":109,"textAnchor":110},"82.4","78.0","font-size:13px;font-weight:700","middle","Capture old",[92,113,116],{"x":107,"y":114,"fill":81,"style":115,"textAnchor":110},"96.0","font-size:12px","snapshot named",[92,118,120],{"x":107,"y":119,"fill":81,"style":115,"textAnchor":110},"112.0","elements",[52,122],{"x":123,"y":99,"width":100,"height":101,"rx":102,"fill":124,"stroke":125,"style":126},"176.8","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[92,128,130],{"x":129,"y":108,"fill":81,"style":109,"textAnchor":110},"231.2","Callback",[92,132,133],{"x":129,"y":114,"fill":81,"style":115,"textAnchor":110},"update DOM",[52,135],{"x":136,"y":99,"width":100,"height":101,"rx":102,"fill":124,"stroke":125,"style":126},"325.6",[92,138,140],{"x":139,"y":108,"fill":81,"style":109,"textAnchor":110},"380.0","Capture new",[92,142,143],{"x":139,"y":114,"fill":81,"style":115,"textAnchor":110},"render + snapshot",[52,145],{"x":146,"y":99,"width":100,"height":101,"rx":102,"fill":103,"stroke":103,"style":104},"474.4",[92,148,150],{"x":149,"y":108,"fill":81,"style":109,"textAnchor":110},"528.8","Animate",[92,152,153],{"x":149,"y":114,"fill":81,"style":115,"textAnchor":110},"pseudo-elements,",[92,155,156],{"x":149,"y":119,"fill":81,"style":115,"textAnchor":110},"compositor",[52,158],{"x":159,"y":99,"width":100,"height":101,"rx":102,"fill":103,"stroke":103,"style":104},"623.2",[92,161,163],{"x":162,"y":108,"fill":81,"style":109,"textAnchor":110},"677.6","Finish",[92,165,166],{"x":162,"y":114,"fill":81,"style":115,"textAnchor":110},"live DOM shown",[168,169],"line",{"x1":170,"y1":171,"x2":172,"y2":171,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":175},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#fa352a2d7b)",[168,177],{"x1":178,"y1":171,"x2":179,"y2":171,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":175},"285.6","323.6",[168,181],{"x1":182,"y1":171,"x2":183,"y2":171,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":175},"434.4","472.4",[168,185],{"x1":186,"y1":171,"x2":187,"y2":171,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":175},"583.2","621.2",[189,190,192],"h2",{"id":191},"rapid-diagnosis","Rapid Diagnosis",[194,195,196,204,213,219],"ul",{},[197,198,199,203],"li",{},[200,201,202],"strong",{},"Record a trace of the interaction"," that triggers the transition; note time from input to first animated frame.",[197,205,206,212],{},[200,207,208,209],{},"Count elements with ",[29,210,211],{},"view-transition-name"," at the time of the transition.",[197,214,215,218],{},[200,216,217],{},"Check the update callback",": does it fetch data or do heavy work before resolving?",[197,220,221,224],{},[200,222,223],{},"Measure transition durations","; long animations keep the page non-interactive.",[189,226,228],{"id":227},"root-cause-analysis","Root Cause Analysis",[14,230,231,234],{},[200,232,233],{},"1. Slow update callbacks."," The new state cannot be captured until the callback resolves, delaying the first frame after input.",[14,236,237,240],{},[200,238,239],{},"2. Many named elements."," Each named element is captured and animated separately, increasing rendering and memory cost.",[14,242,243,246],{},[200,244,245],{},"3. Long animations."," Pointer events go to the transition overlay, not the page, while the transition runs.",[14,248,249,252],{},[200,250,251],{},"4. Large snapshots."," Full-page or very tall named elements produce large textures.",[189,254,256],{"id":255},"step-by-step-resolution","Step-by-Step Resolution",[258,259,261],"h3",{"id":260},"_1-keep-the-dom-update-fast","1. Keep the DOM update fast",[263,264,269],"pre",{"className":265,"code":266,"language":267,"meta":268,"style":268},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","async function showProduct(id) {\n  const data = await fetchProduct(id);                 \u002F\u002F fetch BEFORE starting the transition\n  if (!document.startViewTransition) { render(data); return; }\n  document.startViewTransition(() => render(data));    \u002F\u002F synchronous, fast update\n}\n\u002F\u002F trade-off: fetching first delays the start of the transition, but the transition\n\u002F\u002F itself is short and the page stays interactive while data loads.\n","javascript","",[29,270,271,297,323,350,374,380,386],{"__ignoreMap":268},[272,273,275,279,282,286,290,294],"span",{"class":168,"line":274},1,[272,276,278],{"class":277},"sPARh","async",[272,280,281],{"class":277}," function",[272,283,285],{"class":284},"smZ65"," showProduct",[272,287,289],{"class":288},"saISM","(",[272,291,293],{"class":292},"sQw3B","id",[272,295,296],{"class":288},") {\n",[272,298,300,303,307,310,313,316,319],{"class":168,"line":299},2,[272,301,302],{"class":277},"  const",[272,304,306],{"class":305},"sPXB4"," data",[272,308,309],{"class":277}," =",[272,311,312],{"class":277}," await",[272,314,315],{"class":284}," fetchProduct",[272,317,318],{"class":288},"(id);                 ",[272,320,322],{"class":321},"sjfSM","\u002F\u002F fetch BEFORE starting the transition\n",[272,324,326,329,332,335,338,341,344,347],{"class":168,"line":325},3,[272,327,328],{"class":277},"  if",[272,330,331],{"class":288}," (",[272,333,334],{"class":277},"!",[272,336,337],{"class":288},"document.startViewTransition) { ",[272,339,340],{"class":284},"render",[272,342,343],{"class":288},"(data); ",[272,345,346],{"class":277},"return",[272,348,349],{"class":288},"; }\n",[272,351,353,356,359,362,365,368,371],{"class":168,"line":352},4,[272,354,355],{"class":288},"  document.",[272,357,358],{"class":284},"startViewTransition",[272,360,361],{"class":288},"(() ",[272,363,364],{"class":277},"=>",[272,366,367],{"class":284}," render",[272,369,370],{"class":288},"(data));    ",[272,372,373],{"class":321},"\u002F\u002F synchronous, fast update\n",[272,375,377],{"class":168,"line":376},5,[272,378,379],{"class":288},"}\n",[272,381,383],{"class":168,"line":382},6,[272,384,385],{"class":321},"\u002F\u002F trade-off: fetching first delays the start of the transition, but the transition\n",[272,387,389],{"class":168,"line":388},7,[272,390,391],{"class":321},"\u002F\u002F itself is short and the page stays interactive while data loads.\n",[258,393,395],{"id":394},"_2-limit-named-elements","2. Limit named elements",[14,397,398],{},"Name only the elements that need to morph (a thumbnail becoming a hero, a title moving). Let the rest of the page cross-fade as the root snapshot. Avoid naming every list item; if you must, name only items visible in the viewport.",[258,400,402],{"id":401},"_3-keep-transitions-short","3. Keep transitions short",[14,404,405,406,409],{},"Use 150–300ms for UI transitions. Set durations on ",[29,407,408],{},"::view-transition-group(*)"," and specific groups.",[263,411,415],{"className":412,"code":413,"language":414,"meta":268,"style":268},"language-css shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","::view-transition-group(*) { animation-duration: 220ms; }\n@media (prefers-reduced-motion: reduce) { ::view-transition-group(*) { animation: none; } }\n\u002F* trade-off: shorter transitions look snappier and return interactivity sooner,\n   but very short ones can feel abrupt for large layout changes. *\u002F\n","css",[29,416,417,443,465,470],{"__ignoreMap":268},[272,418,419,422,426,429,432,435,438,441],{"class":168,"line":274},[272,420,421],{"class":288},"::view-transition-group(",[272,423,425],{"class":424},"sZBmE","*",[272,427,428],{"class":288},") { ",[272,430,431],{"class":305},"animation-duration",[272,433,434],{"class":288},": ",[272,436,437],{"class":305},"220",[272,439,440],{"class":277},"ms",[272,442,349],{"class":288},[272,444,445,448,451,453,455,458,460,462],{"class":168,"line":299},[272,446,447],{"class":277},"@media",[272,449,450],{"class":288}," (prefers-reduced-motion: reduce) { ::view-transition-group(",[272,452,425],{"class":424},[272,454,428],{"class":288},[272,456,457],{"class":305},"animation",[272,459,434],{"class":288},[272,461,89],{"class":305},[272,463,464],{"class":288},"; } }\n",[272,466,467],{"class":168,"line":325},[272,468,469],{"class":321},"\u002F* trade-off: shorter transitions look snappier and return interactivity sooner,\n",[272,471,472],{"class":168,"line":352},[272,473,474],{"class":321},"   but very short ones can feel abrupt for large layout changes. *\u002F\n",[258,476,478],{"id":477},"_4-for-cross-document-transitions-avoid-blocking-rendering","4. For cross-document transitions, avoid blocking rendering",[14,480,481,482,485],{},"Cross-document transitions wait for the new page to be ready to render. Keep the new page's critical path fast (critical CSS, no render-blocking scripts), and avoid using ",[29,483,484],{},"\u003Clink rel=\"expect\" blocking=\"render\">"," on elements far down the page, which delays the first frame.",[14,487,488],{},[43,489,50,492,50,495,50,498,50,500,50,503,50,505,50,512,50,519,50,524,50,528,50,533,50,537,50],{"viewBox":490,"width":46,"role":47,"ariaLabel":491,"style":49},"0 0 760 158","Bar chart comparing time from tap to the first animated frame when the view transition callback fetches data versus when data is fetched first.",[52,493],{"className":494,"x":56,"y":56,"width":46,"height":46,"fill":57},[55],[59,496,497],{},"Interaction to first transition frame",[63,499,491],{},[52,501],{"x":85,"y":85,"width":86,"height":502,"rx":88,"fill":89,"stroke":81,"style":90},"156",[92,504,497],{"x":94,"y":95,"fill":81,"style":96},[92,506,511],{"x":507,"y":508,"fill":81,"style":509,"textAnchor":510},"229.5","70.0","font-size:13px","end","Fetch inside callback (page frozen)",[52,513],{"x":514,"y":99,"width":515,"height":516,"rx":517,"fill":89,"stroke":81,"style":518},"241.5","426.5","19","3","fill-opacity:0.7;stroke-opacity:0.35",[92,520,523],{"x":521,"y":508,"fill":81,"style":522},"674.0","font-size:12px;font-weight:600","620ms",[92,525,527],{"x":507,"y":526,"fill":81,"style":509,"textAnchor":510},"101.0","Fetch first then transition",[52,529],{"x":514,"y":530,"width":531,"height":516,"rx":517,"fill":124,"stroke":125,"style":532},"87.0","27.5","fill-opacity:0.7;stroke-opacity:0.9",[92,534,536],{"x":535,"y":526,"fill":81,"style":522},"275.0","40ms",[92,538,542],{"x":94,"y":539,"fill":540,"style":541},"136.0","#51617a","font-size:12.5px","In the second case the fetch still takes ~560ms, but the page stays interactive.",[189,544,546],{"id":545},"verification","Verification",[14,548,549,550,553],{},"Record the interaction: the time from input to the first transition frame should be short (under 100ms) and no long task should precede it. Count named elements during the transition in DevTools (the Elements panel shows ",[29,551,552],{},"::view-transition"," pseudo-elements). Check INP for the triggering interaction in the field, and for cross-document transitions, compare LCP and FCP of navigations with and without the transition.",[189,555,557],{"id":556},"worked-example-a-photo-gallery","Worked Example: A Photo Gallery",[14,559,560,561,563,564,566,567,570,571,573],{},"A photo gallery app used a view transition to morph thumbnails into a full-size viewer. The callback awaited image data and decoding inside ",[29,562,358],{},", and every thumbnail on the page had a ",[29,565,211],{},". Opening a photo froze the page for 400–700ms before animating, and INP for thumbnail taps was 620ms. The team fetched and decoded the image (",[29,568,569],{},"img.decode()",") before starting the transition, and assigned a ",[29,572,211],{}," only to the tapped thumbnail and the viewer image, just before the transition. Time to the first animated frame fell to 45ms, and INP p75 for thumbnail taps to 140ms.",[14,575,576],{},[43,577,50,580,50,583,50,586,50,588,50,595,50,598,50,600,50,605,50,609,50,612,50,616,50,622,50,627,50,631,50,636,50,639,50,643,50,645,50,648,50,651,50,654,50,657,50,660,50,663,50,667,50,670,50,673,50,676,50,679,50,683,50,686,50,690,50,694,50],{"viewBox":578,"width":46,"role":47,"ariaLabel":579,"style":49},"0 0 760 341","Decision sequence for whether a UI change benefits from a view transition and how to set it up.",[52,581],{"className":582,"x":56,"y":56,"width":46,"height":46,"fill":57},[55],[59,584,585],{},"Should this change use a view transition?",[63,587,579],{},[66,589,590],{},[69,591,593],{"id":592,"viewBox":72,"refX":73,"refY":74,"markerWidth":75,"markerHeight":75,"orient":76},"faac5aef01",[78,594],{"d":80,"fill":81,"style":82},[52,596],{"x":85,"y":85,"width":86,"height":597,"rx":88,"fill":89,"stroke":81,"style":90},"339",[92,599,585],{"x":94,"y":95,"fill":81,"style":96},[52,601],{"x":94,"y":99,"width":602,"height":603,"rx":102,"fill":81,"stroke":81,"style":604},"320.0","35.0","fill-opacity:0.06;stroke-opacity:0.4",[92,606,608],{"x":607,"y":108,"fill":81,"style":109,"textAnchor":110},"188.0","Does the update need data or async work?",[52,610],{"x":611,"y":99,"width":602,"height":603,"rx":102,"fill":103,"stroke":103,"style":104},"412.0",[92,613,615],{"x":614,"y":108,"fill":81,"style":541,"textAnchor":110},"572.0","Fetch first, then start the transition",[168,617],{"x1":618,"y1":619,"x2":620,"y2":619,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":621},"348.0","73.5","410.0","url(#faac5aef01)",[92,623,626],{"x":139,"y":624,"fill":103,"style":625,"textAnchor":110},"66.5","font-size:11.5px;font-weight:700","yes",[168,628],{"x1":607,"y1":629,"x2":607,"y2":630,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":621},"91.0","125.0",[92,632,635],{"x":633,"y":634,"fill":540,"style":625},"196.0","113.0","no",[52,637],{"x":94,"y":638,"width":602,"height":603,"rx":102,"fill":81,"stroke":81,"style":604},"127.0",[92,640,642],{"x":607,"y":641,"fill":81,"style":109,"textAnchor":110},"149.0","Do more than a few elements need to morph?",[52,644],{"x":611,"y":638,"width":602,"height":603,"rx":102,"fill":103,"stroke":103,"style":104},[92,646,647],{"x":614,"y":641,"fill":81,"style":541,"textAnchor":110},"Name only those in view; cross-fade the rest",[168,649],{"x1":618,"y1":650,"x2":620,"y2":650,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":621},"144.5",[92,652,626],{"x":139,"y":653,"fill":103,"style":625,"textAnchor":110},"137.5",[168,655],{"x1":607,"y1":656,"x2":607,"y2":633,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":621},"162.0",[92,658,635],{"x":633,"y":659,"fill":540,"style":625},"184.0",[52,661],{"x":94,"y":662,"width":602,"height":603,"rx":102,"fill":81,"stroke":81,"style":604},"198.0",[92,664,666],{"x":607,"y":665,"fill":81,"style":109,"textAnchor":110},"220.0","Is it a frequent action (typing, filtering)?",[52,668],{"x":611,"y":662,"width":602,"height":603,"rx":102,"fill":89,"stroke":81,"style":669},"stroke-opacity:0.35",[92,671,672],{"x":614,"y":665,"fill":81,"style":541,"textAnchor":110},"Skip the transition",[168,674],{"x1":618,"y1":675,"x2":620,"y2":675,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":621},"215.5",[92,677,626],{"x":139,"y":678,"fill":103,"style":625,"textAnchor":110},"208.5",[168,680],{"x1":607,"y1":681,"x2":607,"y2":682,"stroke":81,"strokeWidth":173,"style":174,"markerEnd":621},"233.0","267.0",[92,684,635],{"x":633,"y":685,"fill":540,"style":625},"255.0",[52,687],{"x":94,"y":688,"width":602,"height":689,"rx":102,"fill":124,"stroke":125,"style":126},"269.0","50.0",[92,691,693],{"x":607,"y":692,"fill":81,"style":541,"textAnchor":110},"290.5","Use a short transition (150-300ms) with",[92,695,697],{"x":607,"y":696,"fill":81,"style":541,"textAnchor":110},"306.5","reduced-motion support",[189,699,701],{"id":700},"cross-document-transitions-and-navigation-speed","Cross-Document Transitions and Navigation Speed",[14,703,704],{},"Cross-document view transitions make multi-page sites feel like apps, but they couple the old and new page. The old page's snapshot is held until the new page renders its first frame, then the transition animates. If the new page is slow to render, users see the old page frozen rather than a blank screen — arguably better, but the delay is the same. If the transition adds render-blocking requirements (waiting for specific elements), it can delay first paint. Measure navigation timings with and without the transition; combine with speculation rules (prerendering) to make the new page ready instantly, which is where cross-document transitions look and perform best.",[189,706,708],{"id":707},"measuring-transition-cost","Measuring Transition Cost",[14,710,711,712,714],{},"To see what a transition costs, record two traces of the same interaction — one with ",[29,713,358],{}," and one with the update applied directly. Compare the time from input to the next frame, the rendering work during capture, and the overall time until the page accepts input again. In the field, tag interactions that triggered a transition in your INP reporting, so you can compare INP for transitioned and non-transitioned updates. If transitions add more than a few tens of milliseconds before the first frame, reduce named elements or simplify the update.",[189,716,718],{"id":717},"common-mistakes","Common Mistakes",[194,720,721,727,733,739],{},[197,722,723,726],{},[200,724,725],{},"Doing async work inside the callback."," The page freezes while it waits.",[197,728,729,732],{},[200,730,731],{},"Naming every element."," Snapshot cost and memory grow with each named element.",[197,734,735,738],{},[200,736,737],{},"Long, elaborate animations."," The page is non-interactive for their duration.",[197,740,741,744],{},[200,742,743],{},"Animating the LCP element on navigation."," May delay when it is considered painted.",[189,746,748],{"id":747},"edge-cases","Edge Cases",[14,750,751,754,755,757],{},[200,752,753],{},"Duplicate names."," Two elements with the same ",[29,756,211],{}," abort the transition; ensure uniqueness at capture time.",[14,759,760,763],{},[200,761,762],{},"Scroll position changes."," The root snapshot covers the viewport; transitions involving large scroll changes may look odd and need custom handling.",[14,765,766,769],{},[200,767,768],{},"Third-party content."," Iframes are captured as images; their contents do not animate.",[14,771,772,775],{},[200,773,774],{},"Low-memory devices."," Many large snapshots can be expensive; keep named elements small.",[189,777,779],{"id":778},"faq","FAQ",[781,782,785,789],"details",{"className":783},[784],"faq-item",[786,787,788],"summary",{},"Do view transitions run on the compositor?",[14,790,791],{},"The animation of snapshot pseudo-elements typically uses transforms and opacity and can run on the compositor. Capturing snapshots and updating the DOM happen on the main thread.",[781,793,795,798],{"className":794},[784],[786,796,797],{},"Can the user interact during a view transition?",[14,799,800],{},"No. During the transition, the page is covered by the transition pseudo-elements, so input does not reach the page until it finishes.",[781,802,804,807],{"className":803},[784],[786,805,806],{},"Do view transitions affect INP?",[14,808,809],{},"They can. If the update callback is slow, the next paint after the interaction is delayed. A fast callback and short transition keep INP low.",[781,811,813,816],{"className":812},[784],[786,814,815],{},"Do cross-document transitions slow down navigation?",[14,817,818],{},"They add little overhead if the new page renders quickly. They do not make the new page load faster; combine them with prerendering for instant-feeling navigations.",[781,820,822,825],{"className":821},[784],[786,823,824],{},"How many named elements are reasonable?",[14,826,827],{},"A handful per transition. Each adds snapshot and animation work; name only what needs to morph.",[781,829,831,834],{"className":830},[784],[786,832,833],{},"Can I skip a transition?",[14,835,836,837,840],{},"Yes. Call ",[29,838,839],{},"transition.skipTransition()"," to jump to the end state, useful when a new navigation starts before the previous transition finishes.",[781,842,844,847],{"className":843},[784],[786,845,846],{},"Do view transitions work with frameworks?",[14,848,849,850,852],{},"Yes. Frameworks wrap state updates in ",[29,851,358],{},", and several routers provide built-in integration. Keep the wrapped update synchronous and fast.",[781,854,856,859],{"className":855},[784],[786,857,858],{},"Should I use view transitions for every route change?",[14,860,861],{},"Not necessarily. They suit navigations where continuity helps users understand what changed, like opening an item from a list. For frequent or unrelated navigations, an instant change is often better.",[189,863,865],{"id":864},"related","Related",[194,867,868,875,882],{},[197,869,870,874],{},[18,871,873],{"href":872},"\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fanimating-only-transform-and-opacity\u002F","Animating only transform and opacity"," — custom transition animations.",[197,876,877,881],{},[18,878,880],{"href":879},"\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fscroll-driven-animations-without-javascript\u002F","Scroll-driven animations without JavaScript"," — the other modern animation API.",[197,883,884,888],{},[18,885,887],{"href":886},"\u002Fcore-web-vitals-measurement\u002Foptimizing-inp-with-scheduler-yield\u002F","Optimizing INP with scheduler.yield"," — keeping interactions responsive.",[890,891,893],"script",{"type":892},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"View Transitions API Performance\",\n  \"description\": \"How same-document and cross-document view transitions work, what they cost, and how to use them without hurting INP, LCP or memory.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Keep the DOM update fast\",\n      \"text\": \"Keep the DOM update fast\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Limit named elements\",\n      \"text\": \"Name only the elements that need to morph (a thumbnail becoming a hero, a title moving).\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Keep transitions short\",\n      \"text\": \"Use 150–300ms for UI transitions.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"For cross-document transitions, avoid blocking rendering\",\n      \"text\": \"Cross-document transitions wait for the new page to be ready to render.\"\n    }\n  ]\n}\n",[890,895,896],{"type":892},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"View Transitions API Performance\",\n  \"description\": \"How same-document and cross-document view transitions work, what they cost, and how to use them without hurting INP, LCP or memory.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance\u002F\"\n  }\n}\n",[890,898,899],{"type":892},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Rendering & CSS Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Animation & Compositing Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"View Transitions API Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance\u002F\"\n    }\n  ]\n}\n",[901,902,903],"style",{},"html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}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 .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}",{"title":268,"searchDepth":299,"depth":299,"links":905},[906,907,908,914,915,916,917,918,919,920,921],{"id":191,"depth":299,"text":192},{"id":227,"depth":299,"text":228},{"id":255,"depth":299,"text":256,"children":909},[910,911,912,913],{"id":260,"depth":325,"text":261},{"id":394,"depth":325,"text":395},{"id":401,"depth":325,"text":402},{"id":477,"depth":325,"text":478},{"id":545,"depth":299,"text":546},{"id":556,"depth":299,"text":557},{"id":700,"depth":299,"text":701},{"id":707,"depth":299,"text":708},{"id":717,"depth":299,"text":718},{"id":747,"depth":299,"text":748},{"id":778,"depth":299,"text":779},{"id":864,"depth":299,"text":865},"How same-document and cross-document view transitions work, what they cost, and how to use them without hurting INP, LCP or memory.","md",{"slug":12,"type":925,"breadcrumb":926,"datePublished":934,"dateModified":934},"article",[927,930,931,932],{"name":928,"url":929},"Home","\u002F",{"name":26,"url":25},{"name":21,"url":20},{"name":5,"url":933},"\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance\u002F","2026-10-06",true,"\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance",{"title":938,"description":939},"View Transitions API Performance: Costs and Best Practice","View Transitions snapshot old and new states, which costs rendering time and memory and can delay INP. Keep transitions short, named groups few, and avoid blocking.","rendering-css-performance\u002Fanimation-and-compositing-performance\u002Fview-transitions-api-performance\u002Findex","jkv68jr0ZAE6Xb-11T3SeTBWH49Ma-Cl7Mwwvx7cX_s",[943,947],{"title":944,"path":945,"stem":946,"children":-1},"Scroll-Driven Animations Without JavaScript","\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fscroll-driven-animations-without-javascript","rendering-css-performance\u002Fanimation-and-compositing-performance\u002Fscroll-driven-animations-without-javascript\u002Findex",{"title":948,"path":949,"stem":950,"children":-1},"will-change Overuse and Layer Explosion","\u002Frendering-css-performance\u002Fanimation-and-compositing-performance\u002Fwill-change-overuse-and-layer-explosion","rendering-css-performance\u002Fanimation-and-compositing-performance\u002Fwill-change-overuse-and-layer-explosion\u002Findex",1791308073080]