Introduction a la View Transitions API
La View Transitions API est une nouvelle API native qui permet de creer des transitions fluides entre differents etats du DOM ou entre pages entieres. Fini les librairies JavaScript complexes pour animer vos changements de page !
Avant cette API, creer des transitions de page necessitait des solutions comme :
- Barba.js ou Swup pour les transitions SPA
- FLIP animations complexes avec JavaScript
- CSS transitions limitees aux proprietes animables
Avec la View Transitions API, le navigateur gere nativement la capture d'ecran, l'interpolation et l'animation entre deux etats. Le resultat : des performances optimales et un code beaucoup plus simple.
La View Transitions API fonctionne aussi bien pour les Single Page Applications (SPA) que pour les Multi Page Applications (MPA). Les transitions MPA necessitent Chrome 126+ avec une meta tag specifique.
Syntaxe de base : document.startViewTransition()
La methode principale de l'API est document.startViewTransition(). Elle prend une fonction callback qui effectue les modifications du DOM.
Transition simple
Voici l'implementation la plus basique pour animer un changement de contenu :
// Fonction qui modifie le DOM
function updateContent() {
document.querySelector('.content').innerHTML = newContent;
}
// Verifier le support de l'API
if (!document.startViewTransition) {
// Fallback : mise a jour directe sans animation
updateContent();
return;
}
// Creer une transition animee
document.startViewTransition(() => {
updateContent();
});
Transition avec Promise
La methode retourne un objet ViewTransition avec plusieurs proprietes utiles :
const transition = document.startViewTransition(async () => {
// Charger le nouveau contenu
const response = await fetch('/api/content');
const html = await response.text();
document.querySelector('.content').innerHTML = html;
});
// Attendre que la transition soit prete
await transition.ready;
console.log('Transition demarree');
// Attendre la fin de l'animation
await transition.finished;
console.log('Transition terminee');
L'objet ViewTransition expose trois promises :
- updateCallbackDone : resolue quand le callback est termine
- ready : resolue quand l'animation peut commencer
- finished : resolue quand l'animation est terminee
Transitions CSS personnalisees
Par defaut, la View Transitions API applique un simple fondu enchaine (crossfade). Mais vous pouvez personnaliser entierement les animations avec des pseudo-elements CSS.
Les pseudo-elements de transition
Pendant une transition, le navigateur cree une structure de pseudo-elements :
::view-transition
::view-transition-group(root)
::view-transition-image-pair(root)
::view-transition-old(root) /* Capture de l'ancien etat */
::view-transition-new(root) /* Capture du nouvel etat */
Animation de fondu personnalisee
Voici comment creer une animation de fondu avec un effet de zoom :
/* Animation de l'ancien etat (sortie) */
::view-transition-old(root) {
animation: 300ms ease-out fade-out-scale;
}
/* Animation du nouvel etat (entree) */
::view-transition-new(root) {
animation: 300ms ease-out fade-in-scale;
}
@keyframes fade-out-scale {
to {
opacity: 0;
transform: scale(0.9);
}
}
@keyframes fade-in-scale {
from {
opacity: 0;
transform: scale(1.1);
}
}
Animation de glissement
Pour une transition de type slide entre pages :
/* Slide vers la gauche (avancer) */
::view-transition-old(root) {
animation: 400ms cubic-bezier(0.4, 0, 0.2, 1) slide-out-left;
}
::view-transition-new(root) {
animation: 400ms cubic-bezier(0.4, 0, 0.2, 1) slide-in-right;
}
@keyframes slide-out-left {
to {
opacity: 0;
transform: translateX(-100px);
}
}
@keyframes slide-in-right {
from {
opacity: 0;
transform: translateX(100px);
}
}
/* Slide inverse (reculer) - ajouter une classe sur html */
html.back-navigation::view-transition-old(root) {
animation-name: slide-out-right;
}
html.back-navigation::view-transition-new(root) {
animation-name: slide-in-left;
}
Demo : cliquez sur les onglets pour voir la transition
Transitions entre pages (MPA)
La fonctionnalite la plus attendue : les transitions entre pages dans les applications multi-pages classiques. Plus besoin de SPA pour avoir des transitions fluides !
Activer les transitions MPA
Ajoutez simplement cette meta tag dans le <head> de chaque page :
<head>
<!-- Activer les transitions entre pages -->
<meta name="view-transition" content="same-origin">
</head>
Les transitions MPA ne fonctionnent qu'entre pages de la meme origine (same-origin). Les navigations vers des domaines externes ne declencheront pas de transition.
Personnaliser la direction de transition
Utilisez JavaScript pour definir la direction selon la navigation :
// Detecter le sens de navigation
window.addEventListener('pageswap', (event) => {
const navigation = performance.getEntriesByType('navigation')[0];
if (navigation.type === 'back_forward') {
document.documentElement.classList.add('back-navigation');
}
});
// Nettoyer apres la transition
window.addEventListener('pagereveal', () => {
document.documentElement.classList.remove('back-navigation');
});
Animations d'elements partages
La vraie puissance de l'API reside dans les transitions d'elements partages. Un element peut "voler" d'une position a une autre entre deux etats.
Nommer les elements de transition
Utilisez la propriete CSS view-transition-name pour identifier les elements qui doivent avoir leur propre animation :
/* Page liste : carte produit */
.product-card img {
view-transition-name: product-image;
}
.product-card h3 {
view-transition-name: product-title;
}
/* Page detail : memes noms */
.product-hero img {
view-transition-name: product-image;
}
.product-hero h1 {
view-transition-name: product-title;
}
Chaque view-transition-name doit etre unique dans le document. Si deux elements ont le meme nom en meme temps, la transition echouera silencieusement.
Noms dynamiques avec JavaScript
Pour les listes d'elements, assignez les noms dynamiquement :
// Au clic sur une carte
card.addEventListener('click', (e) => {
const productId = card.dataset.id;
// Assigner un nom unique a cette carte
card.querySelector('img').style.viewTransitionName = `product-${productId}`;
// Naviguer vers la page detail
window.location.href = `/product/${productId}`;
});
Personnaliser l'animation d'un element partage
/* Le groupe gere la position et la taille */
::view-transition-group(product-image) {
animation-duration: 500ms;
animation-timing-function: cubic-bezier(0.4, 0, 0, 1);
}
/* L'ancien etat disparait progressivement */
::view-transition-old(product-image) {
animation: 250ms ease-out fade-out;
}
/* Le nouvel etat apparait progressivement */
::view-transition-new(product-image) {
animation: 250ms ease-in 250ms fade-in;
}
Demo : cliquez sur un element pour simuler une transition partagee
Support navigateurs et fallbacks
La View Transitions API est encore relativement recente. Voici l'etat du support actuel :
| Navigateur | SPA (same-document) | MPA (cross-document) | Version minimale |
|---|---|---|---|
| Chrome | Oui | Oui | 111+ / 126+ |
| Edge | Oui | Oui | 111+ / 126+ |
| Opera | Oui | Oui | 97+ / 112+ |
| Safari | Oui | Non | 18+ |
| Firefox | Flag | Non | - |
Detection de fonctionnalite
// Verifier le support JavaScript
const supportsViewTransitions = 'startViewTransition' in document;
// Verifier le support CSS
const supportsCSSViewTransitions = CSS.supports('view-transition-name', 'test');
// Fonction wrapper avec fallback
function navigate(updateFn) {
if (!supportsViewTransitions) {
updateFn();
return;
}
document.startViewTransition(updateFn);
}
CSS avec fallback
/* Styles de transition uniquement si supporte */
@supports (view-transition-name: test) {
.hero-image {
view-transition-name: hero;
}
::view-transition-old(hero),
::view-transition-new(hero) {
animation-duration: 400ms;
}
}
Exemples pratiques
Exemple 1 : Theme switch avec transition
Un classique : le changement de theme clair/sombre avec une animation elegante.
Cliquez sur le toggle pour changer de theme avec transition.
Demo : changement de theme avec View Transitions
const toggle = document.querySelector('#theme-toggle');
toggle.addEventListener('click', async () => {
// Fallback sans animation
if (!document.startViewTransition) {
document.documentElement.classList.toggle('dark');
return;
}
// Avec transition animee
const transition = document.startViewTransition(() => {
document.documentElement.classList.toggle('dark');
});
// Animer depuis le bouton toggle
await transition.ready;
const { top, left, width, height } = toggle.getBoundingClientRect();
const x = left + width / 2;
const y = top + height / 2;
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
);
document.documentElement.animate(
{
clipPath: [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`
]
},
{
duration: 500,
easing: 'ease-out',
pseudoElement: '::view-transition-new(root)'
}
);
});
Exemple 2 : Navigation SPA
Implementez des transitions fluides dans votre Single Page Application.
// Router simple avec View Transitions
class Router {
constructor() {
this.routes = new Map();
this.container = document.querySelector('#app');
// Intercepter les clics sur les liens
document.addEventListener('click', (e) => {
const link = e.target.closest('a[href^="/"]');
if (link) {
e.preventDefault();
this.navigate(link.pathname);
}
});
}
register(path, handler) {
this.routes.set(path, handler);
}
async navigate(path) {
const handler = this.routes.get(path);
if (!handler) return;
const updateDOM = async () => {
this.container.innerHTML = await handler();
history.pushState(null, '', path);
};
// Avec View Transition si supporte
if (document.startViewTransition) {
await document.startViewTransition(updateDOM).finished;
} else {
await updateDOM();
}
}
}
// Utilisation
const router = new Router();
router.register('/', () => '<h1>Accueil</h1>');
router.register('/about', () => '<h1>A propos</h1>');
Exemple 3 : Galerie d'images
Transition fluide entre miniature et plein ecran.
const gallery = document.querySelector('.gallery');
const modal = document.querySelector('.modal');
const modalImg = modal.querySelector('img');
gallery.querySelectorAll('img').forEach((img, index) => {
img.addEventListener('click', () => {
// Assigner un nom unique
img.style.viewTransitionName = 'gallery-image';
modalImg.style.viewTransitionName = 'gallery-image';
const transition = document.startViewTransition(() => {
modalImg.src = img.src;
modal.classList.add('open');
});
transition.finished.then(() => {
// Nettoyer les noms apres la transition
img.style.viewTransitionName = '';
});
});
});
Les View Transitions utilisent le compositing GPU. L'animation se fait sur des "screenshots" des etats, ce qui garantit 60fps meme avec des DOM complexes.
Conclusion
La View Transitions API represente une avancee majeure pour l'experience utilisateur sur le web. Elle permet enfin de creer des transitions de page natives, performantes et faciles a implementer.
Points cles a retenir :
- Simple a utiliser : une seule methode
document.startViewTransition() - Entierement personnalisable avec CSS et les pseudo-elements dedies
- Elements partages : la propriete
view-transition-namepermet des animations "hero" - MPA support : fonctionne aussi entre vraies pages HTML
- Progressive enhancement : facile a implementer avec fallback
Le support navigateur s'ameliore rapidement. C'est le moment ideal pour commencer a experimenter avec cette API et preparer vos projets pour le futur du web !
Decouvrez nos templates premium qui utilisent la View Transitions API pour des experiences utilisateur exceptionnelles.