# view-transitions Jens Grochtdreis | unkonf Mannheim, 2026 ## Agenda 1. Das Ausgangsproblem 2. Same-Document transitions 3. Die neuen Pseudoelemente 4. Cross-Document transitions 5. ziemlich geniale Beispiele ## Das Ausgangsproblem Bei einem Seitenwechel oder einem Wechsel des Zustands einer Seite (z.B. ein Modal öffnen) passiert der Wechsel sofort. Das kann zu einem unschönen "Ruckeln" führen. ### Zwei Lösungen 1. Auf der selben Seite bleiben und animieren (Same-Document View Transitions). 2. Auf eine andere Seite wechseln und dabei animieren (Cross-Document View Transitions). ### Wo View Transitions greifen
Navigation
Seitenwechsel, Tab-Umschaltung, Routing
Interaktionen
Filter, Favoriten, Modals, Karten-Details
State-Umschaltungen
Dark Mode, Layout-Mode, Produktstatus
Special Effects
Morphing von Icons, Chips, Bildern oder Panels
### Die neue API **[View Transitions](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API)** regeln den Übergang zwischen zwei Zuständen einer Seite oder zwischen zwei Seiten. Javascript ist nur nötig, wenn man die Animationen steuern möchte und wenn man auf der selben Seite bleibt. Zwischen Seiten kann man die API auch ohne Javascript nutzen. ### Browser support Same-Document View Transitions sind seit Oktober 2025 **Baseline**.
Cross-Document View Transitions bietet Firefox leider noch nicht.
### Snapshots sind die Grundlage * "Snapshot" des aktuellen Zustands * "Snapshot" des neuen Zustands * Automatische Erstellung einer Morphing-Animation zwischen passenden Elementen ### Drei Phasen 1. **Phase 1** 1. auf der gleichen Seite per JS: "Ich mache gleich was im DOM, pass auf!" 2. beim Seitenwechsel schlicht per CSS 2. **Phase 2 (Browser):** Der Browser friert den Zustand ein (`snapshot`), führt deinen Code aus und friert den neuen Zustand ein. Er berechnet automatisch, welche Elemente sich geändert haben. 3. **Phase 3 (CSS):** Du definierst, wie sich der alte Zustand in den neuen verwandelt. ## Same-Document Bleibt man auf derselben Seite und animiert den Übergang zwischen zwei Zuständen, benötigt man JavaScript zum Triggern der Animation: ```javascript // Ein- und Ausblenden eines Dialogs const dialog = document.querySelector("#dialog"); document.querySelector("#open").addEventListener("click", () => { document.startViewTransition?.(() => dialog.showModal()); }); document.querySelector("#close").addEventListener("click", () => { document.startViewTransition?.(() => dialog.close()); }); ``` Wir benötigen hier JavaScript, weil der Browser nicht weiß, wann und wie sich der Inhalt einer Seite ändert, wenn kein echter Seitenwechsel stattfindet. ### Demo 1: einfaches morphen [Zeigt](demos/einfaches-morphen.html), wie `startViewTransition()` ohne jegliches CSS automatisch morphed. ### Demo 2: einfaches morphen für einen Zweck - [Code-Manipulation](demos/view-transition-local-dev-prototype.html) mit direkter Demonstration - [Eine Galerie](https://codepen.io/jensgro/full/ogZBQQz) (auf Codepen) ### Es werden Bilder gemorpht Da die Snapshots und nicht die Elemente gemorpht werden, kann aus einem Bild oder einem Button auch ohne Probleme ein Modalfenster werden. Das zeigt [Adam Argyle](https://codepen.io/argyleink/full/qEWeYzd) auf Codepen. ### Weitere Beispiele - [Animierte Zahlen](https://codepen.io/argyleink/full/jOQKdeW) (von Adam Argyle) - [Anzahl der Grid-Items ändern](https://codepen.io/jensgro/pen/wBJgQNX) (von Adam Argyle) - [animiertes Tabinterface 1](https://codepen.io/ghaste/full/MWNgaWm) (von Amit Ghaste) - [animiertes Tabinterface 2](https://codepen.io/Ducs/full/RNwGBpE) (von Descamps) ## Die neuen Pseudoelemente ```css .element { /* NUR diese Zeile macht das Element morphbar */ /* Der Name findet sich in den Pseudoelementen wieder. */ view-transition-name: element; } /* ----------------------------------------------------------- */ /* Der Container für ein spezifisches Element. Wird gemorpht. */ ::view-transition-group(element) {} /* Der alte Zustand */ ::view-transition-old(element) {} /* Der neue Zustand */ ::view-transition-new(element) {} ``` - Nur Elemente mit dem passenden `view-transition-name` werden animiert. Alle anderen Elemente werden sofort ersetzt. - Sie sind nur für die Animation zuständig und haben keine eigene Logik. - Sie können mit CSS-Animationen oder Transitionen animiert werden. - Sie können auch mit `mix-blend-mode` kombiniert werden, um kreative Effekte zu erzielen. - Die Zustände sind **Snapshots**, also Bilder der Elemente. ### Ein Beispiel ```css .card { /* NUR diese Zeile macht das Element morphbar */ view-transition-name: card; } /* Der Container der gemorpht wird */ ::view-transition-group(card) { animation-duration: 0.8s; animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55); } /* Der alte Zustand: fade out + rotate */ ::view-transition-old(card) { animation: fade-rotate-out 0.4s ease-in forwards; } /* Der neue Zustand: fade in + scale */ ::view-transition-new(card) { animation: scale-in 0.4s 0.4s ease-out forwards; } ``` Mit [benannten Gruppen](demos/die-neuen-pseudoelemente.html) die Animation gezielt steuern. ### Blur & Crossfade Dieses Beispiel lässt den [alten Zustand ausblenden und den neuen mit Blur erscheinen](demos/blur-crossfade.html). ```css ::view-transition-group(content) { animation-duration: 0.6s; mix-blend-mode: difference;} ::view-transition-old(content) { animation: blur-out 0.3s ease-in forwards;} ::view-transition-new(content) { animation: blur-in 0.3s 0.3s ease-out forwards;} @keyframes blur-out { to { opacity: 0; filter: blur(12px); transform: scale(1.1); } } @keyframes blur-in { from { opacity: 0; filter: blur(12px); transform: scale(0.9); } to { opacity: 1; filter: blur(0); transform: scale(1); } } ``` ## Cross-Document View-Transitions können auch beim Wechsel zwischen verschiedenen Seiten genutzt werden. Dabei werden die Snapshots der Elemente auf der alten Seite mit denen auf der neuen Seite gemorpht, sofern die `view-transition-name` übereinstimmen. Dafür benötigen wir nur CSS. [Im CSS des ersten Beispiels](demos/vt-1.html) können wir mit ein paar Modifikationen die Animation anpassen. ### Wir merken uns ```css /* Das triggert die View-Transition beim Seitenwechsel */ @view-transition { navigation: auto; } ``` Wenn wir es gut machen wollen: ```css @media (prefers-reduced-motion: no-preference) { @view-transition { navigation: auto; } } ``` Der Standardübergang ist ein **cross-fade**. ### Ein eigener Cross-fade ```css ::view-transition-old(root) { animation: fade-out 0.3s ease both;} ::view-transition-new(root) { animation: fade-in 0.3s ease both;} @keyframes fade-out { to {opacity: 0; } } @keyframes fade-in { from {opacity: 0;} } ``` [Eigene Animation erstellen (lassen)](https://tools.digrart.jp/de/css-view-transition-generator/) ### Inhalte animieren, nicht ganze Seiten - [nur die Bilder eines Teasers](demos/vt-2.html) - [Bilder und Headlines eines Teasers](demos/vt-3.html) ### Während der Animation Während der Animation können wir Elemente gezielt stylen, z. B. um sie hervorzuheben oder auszublenden: ```css h2 { display: none; color: white; } root:active-view-transition h2 { display: block; } html:active-view-transition button { visibility: hidden; } ``` `:active-view-transition` ist die Pseudo-Klasse, die während der Animation aktiv ist. Sie bezieht sich immer auf das Root-Element, also auf das ``-Element. ### Ziemlich geniale Beispiele - [Cards](https://live-transitions.pages.dev) deren Inhalt beim Wechsel zwischen den Karten animiert wird. - Mit modernen Methoden [Seitenübergänge wie im IE5.5](https://page-transitions.style) erzeugen. ## Zusammenfassung View Transitions bestehen aus **drei Phasen**, und CSS hat nur in einer davon die Kontrolle: 1. AUSLÖSEN 1. auf der gleichen Seite → JS: ``document.startViewTransition(callback)`` 2. ein Seitenwechsel → CSS: ``@view-transition {navigation: auto;}`` 2. SNAPSHOTTEN → Browser: automatisch (alt + neu) 3. ANIMIEREN → CSS: ::view-transition-old / -new / group | Begriff / Selektor | Was es ist | Wann du es nutzt | |---|---|---| | **`document.startViewTransition()`** | JS-API zum Auslösen | Immer bei Same-Document (SPA, Tabs, Filter) | | **`view-transition-name`** | CSS-Property am Element | **Pflicht**, damit der Browser das Element morphen kann | | **`::view-transition-group(name)`** | Container der Animation | Steuert Timing, Dauer, Easing (die „Hülle") | | **`::view-transition-old(name)`** | Der „alte" Zustand (Snapshot) | Styling des Ausgangsbilds (z. B. `opacity: 0`, `rotate`) | | **`::view-transition-new(name)`** | Der „neue" Zustand (Snapshot) | Styling des Zielbilds (z. B. `scale(0.5)` → `scale(1)`) | | **`@view-transition`** | CSS-At-Rule (Cross-Document) | **Nur** bei echter Navigation zwischen HTML-Dateien | | **`:active-view-transition`** | Pseudo-Klasse | Möglichkeit, Elemente während der Animation zu stylen | | | Same-Document | Cross-Document | |---|---|---| | **Trigger** | `document.startViewTransition()` | `@view-transition {navigation: auto;}` | | **DOM-Update** | Dein JS-Code | Echte Navigation | | **Styling** | `::view-transition-*` | `::view-transition-*` | | **Browser** | ✅ Alle (Baseline seit 10/2025) | Firefox fehlt noch | | **Use-Case** | SPA, Tabs, Filter, Modals | Websites mit echter Navigation | ### Wichtige Links * [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) – Die Referenz für beide Levels (Same-Document & Cross-Document) bei MDN. * [Massenweise Beispiele](https://view-transitions.chrome.dev) von Bramus Van Damme (Google) * [View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) – Offizielle Dokumentation und Beispiele vom Google Chrome Dev Team. * [The View Transitions API in 2026: :active-view-transition](https://brainstormsandraves.com/css/view-transitions-2026/) – Überblick über den aktuellen Support (2026) und die Unterschiede zwischen Level 1 und 2. * [Cross-Document View Transitions: The Gotchas Nobody Mentions](https://css-tricks.com/cross-document-view-transitions-part-1/), [Cross-Document View Transitions: Scaling Across Hundreds of Elements](https://css-tricks.com/cross-document-view-transitions-part-2/) von CSS-Tricks ### Entwicklung & Debugging In den **Chrome DevTools** im Tab **"View Transitions"** (unter "Elements" oder "Performance") nutzen. Hier sieht man die Snapshots und die Namen der Gruppen, also die neuen Pseudoelemente. ## Das war's 
Grochtdreis.de
CSS-Weblog.de
Meine Kochrezepte
@jensgro@mastodon.social
## EINEN hab' ich noch: FAQ ### Kann ich View Transitions mit React/Vue/Svelte nutzen? Ja, aber Vorsicht im Strict Mode. In React 18+ muss man `startViewTransition()` oft in einen `useLayoutEffect` oder `flushSync` packen, damit der DOM-Update synchron ist, bevor die Transition startet. In Svelte 5 ist es einfacher, da es native Support für `view-transition-name` gibt. Für genauere Informationen siehe die Dokumentation der jeweiligen Frameworks oder frage eine [AI](https://duck.ai) deines Vertrauens. ### Ist das barrierefrei? Screenreader lesen den Inhalt der Snapshots nicht, da sie Bilder sind. Wichtig: Das DOM-Update passiert unter der Haube während der Animation. Achte darauf, dass `aria-live` Regionen oder Fokus-Management (`focus()`) trotzdem korrekt funktionieren, sonst ist die Seite nach der Transition unsichtbar für Tastaturnutzer. ### Warum wird meine Transition übersprungen (skipped)? Meistens weil das DOM-Update **nicht synchron** passiert. Wenn du `setTimeout` oder `await` im Callback nutzt, denkt der Browser, das Update ist fertig, und bricht ab. Oder: Das Element hat keinen `view-transition-name` (bei Cross-Document) oder das Update ist zu komplex für den Snapshot-Prozess. ### Kann ich mehrere Elemente gleichzeitig morphren? Ja, aber jedes braucht einen **einzigartigen** `view-transition-name`. Wenn zwei Elemente den gleichen Namen haben, crasht die Transition oder wird ignoriert. Tipp: Nutze Präfixe wie `card-1`, `card-2`. ### Wie gehe ich mit Bildern um, die ihre Größe ändern? Bilder werden standardmäßig *gestretched*, nicht gezoomt. Fix in CSS: ```css ::view-transition-old(my-img), ::view-transition-new(my-img) { object-fit: cover; /* oder contain */ } ``` ### Gibt es einen Performance-Overhead? Der Snapshot-Prozess ist GPU-beschleunigt, aber er dupliziert den DOM-Baum visuell. Bei sehr komplexen Seiten (hunderte von Elementen) kann es ruckeln. Tipp: Nur Elemente mit `view-transition-name` markieren, die sich wirklich bewegen. Alles andere bleibt „normal" und wird nicht gesnapshottet.