Blog / JavaScript / CSS

View Transitions API : le guide complet

Maitrisez la View Transitions API pour creer des transitions de page fluides et des animations d'elements partages. Une API native qui revolutionne l'experience utilisateur sur le web.

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.

💡
Bon a savoir

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 :

basic-transition.js
// 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 :

transition-promises.js
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 :

pseudo-elements.txt
::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 :

custom-fade.css
/* 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-transition.css
/* 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-meta.html
<head>
    <!-- Activer les transitions entre pages -->
    <meta name="view-transition" content="same-origin">
</head>
⚠️
Important

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 :

navigation-direction.js
// 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 :

shared-elements.css
/* 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;
}
💡
Regle importante

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 :

dynamic-names.js
// 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

shared-animation.css
/* 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

feature-detection.js
// 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

css-fallback.css
/* 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.

Mode actuel

Cliquez sur le toggle pour changer de theme avec transition.

Demo : changement de theme avec View Transitions

theme-switch.js
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.

spa-navigation.js
// 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.

image-gallery.js
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 = '';
        });
    });
});
🚀
Performance

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-name permet 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 !

🎯
Allez plus loin

Decouvrez nos templates premium qui utilisent la View Transitions API pour des experiences utilisateur exceptionnelles.