next.jsanimationercss og layouts

View Transitions i Next.js: sideanimationer uden animationsbibliotek

View Transitions i Next.js: sideanimationer uden animationsbibliotek

View Transitions API tager det trick fra dig og giver det til browseren. I stedet for at holde to levende DOM-træer og måle dem, fotograferer browseren den gamle tilstand, lader DOM opdatere, fotograferer den nye tilstand og animerer mellem de to billeder – på compositoren.

javascript

function navigate(update) {
if (!document.startViewTransition) {
update(); // ingen support: bare opdater, ingen animation
return;
}
document.startViewTransition(() => update());
}

css

::view-transition /* overlejringen der dækker hele siden */
::view-transition-group(name) /* animerer størrelse og position */
::view-transition-image-pair(name)
::view-transition-old(name) /* "før"-snapshottet */
::view-transition-new(name) /* "efter"-snapshottet */

Det der overrasker alle: et snapshot er et fotografi, ikke et element

::view-transition-old er ikke dit gamle element, bare renderet mindre. Det er et statisk billede af det. Et <video> fryser på én frame. En spinner holder op med at dreje. Ved 200ms spiller intet af det nogen rolle. Ved 1000ms bliver alt åbenlyst.

Navngivning: hele kontrakten

css

.card-image {
view-transition-name: hero;
}
::view-transition-group(hero) {
animation-duration: 400ms;
animation-timing-function: ease-in-out;
}

Den hårde regel: et view-transition-name skal være unikt i dokumentet til enhver tid.

React 19.2 og Next.js 16: én 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 og default="none" skal rejse sammen. Med default="none" og ingen share-prop holder det navngivne par stille op med at morphe.

Retning: fortæl brugeren hvilken vej de gik

tsx

<Link href="/projects/runvalis" transitionTypes={["nav-forward"]}>
Runvalis
</Link>
<ViewTransition
enter={{ "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 uden noget framework

css

@view-transition {
navigation: auto;
}

Faldgruber og bedste praksis

  • Altid behandl som progressiv forbedring.
  • Fejlsøg i slowmotion.
  • Respektér prefers-reduced-motion.
  • Overlejringen spiser klik som standard.
  • Snapshots koster hukommelse.
  • Forankr headeren.
  • En view transition er usynlig for hjælpeteknologi.

Konklusion

View Transitions er det samme argument anvendt på navigation: i stedet for at køre FLIP i hånden, erklærer du hvad der forbinder to tilstande og lader browseren tegne forbindelsen fra to fotografier.