View Transitions i Next.js: sidanimationer utan animationsbibliotek
View Transitions i Next.js: sidanimationer utan animationsbibliotek
View Transitions API tar det tricket från dig och ger det till webbläsaren. Istället för att hålla två levande DOM-träd och mäta dem fotograferar webbläsaren det gamla tillståndet, låter DOM uppdateras, fotograferar det nya tillståndet och animerar mellan de två bilderna – på compositorn.
javascript
function navigate(update) {if (!document.startViewTransition) {update(); // inget stöd: bara uppdatera, ingen animationreturn;}document.startViewTransition(() => update());}
css
::view-transition /* överlägget som täcker hela sidan */::view-transition-group(name) /* animerar storlek och position */::view-transition-image-pair(name)::view-transition-old(name) /* "före"-ögonblicksbilden */::view-transition-new(name) /* "efter"-ögonblicksbilden */
Det som förvånar alla: en ögonblicksbild är ett fotografi, inte ett element
::view-transition-old är inte ditt gamla element renderat mindre. Det är en statisk bild av det. En <video> fryser på en frame. En spinner slutar snurra. Vid 200ms spelar inget av det någon roll. Vid 1000ms blir allt uppenbart.
Namngivning: hela kontraktet
css
.card-image {view-transition-name: hero;}::view-transition-group(hero) {animation-duration: 400ms;animation-timing-function: ease-in-out;}
Den hårda regeln: ett view-transition-name måste vara unikt i dokumentet vid varje givet tillfälle.
React 19.2 och Next.js 16: en komponent
tsx
import { ViewTransition } from "react";import Image from "next/image";import Link from "next/link";export function ProjectCard({ project }) {return (<Link href={"/projects/" + project.slug}><ViewTransition name={"project-" + project.slug}><Image src={project.cover} alt={project.title} /></ViewTransition></Link>);}
share och default="none" måste följa med varandra. Med default="none" och ingen share-prop slutar det namngivna paret tyst att morpha.
Riktning: tala om för användaren åt vilket håll de gick
tsx
<Link href="/projects/runvalis" transitionTypes={["nav-forward"]}>Runvalis</Link><ViewTransitionenter={{ "nav-forward": "slide-in", "nav-back": "slide-out", default: "none" }}exit={{ "nav-forward": "slide-out", "nav-back": "slide-in", default: "none" }}default="none"><main>{children}</main></ViewTransition>
Versionen utan något ramverk
css
@view-transition {navigation: auto;}
Fallgropar och bästa praxis
- Behandla alltid som progressiv förbättring.
- Felsök i slow motion.
- Respektera
prefers-reduced-motion. - Överlägget äter klick som standard.
- Ögonblicksbilder kostar minne.
- Förankra headern.
- En view transition är osynlig för hjälpmedel.
Slutsats
View Transitions är samma argument tillämpad på navigering: istället för att köra FLIP för hand deklarerar du vad som förbinder två tillstånd och låter webbläsaren rita förbindelsen från två fotografier.