Retour au cours

frontend / css

View Transitions API

Leçon 211 exercice

Explication

Ce que vous allez apprendre

  • Déclencher une transition animée entre deux états du DOM avec document.startViewTransition()
  • Comprendre pourquoi le callback passé doit rester synchrone
  • Isoler un élément avec view-transition-name pour un effet de morphing fluide
  • Prévoir un repli propre pour les navigateurs qui ne supportent pas l'API
  • Activer les transitions natives entre pages en navigation multi-page (MPA)

Dans quel contexte ?

Une application de galerie photo doit animer le passage d'une vignette en grille vers sa vue détail en plein écran, avec un effet de "morphing" fluide où l'image agrandit et se déplace naturellement, plutôt que de disparaître puis réapparaître brutalement. Reproduire cet effet à la main en JavaScript demandait auparavant de calculer soi-même les positions de départ et d'arrivée ; la View Transitions API fait ce calcul nativement.

Étape 1 : un changement historiquement brutal

Passer d'une page à une autre, ou changer le contenu d'une application, produit historiquement un changement BRUTAL : l'ancien contenu disparaît instantanément, le nouveau apparaît d'un coup.

Étape 2 : ce que ça demandait avant

Créer une transition fluide entre ces deux états demandait auparavant des bibliothèques JavaScript entières dédiées à l'animation. La View Transitions API résout ce problème nativement.

Étape 3 : comprendre le mécanisme avant/après

Le fonctionnement est conceptuellement simple : document.startViewTransition() prend une "photo" de l'état actuel, exécute le code qui produit le nouvel état, prend une seconde photo, puis anime automatiquement la différence.

Étape 4 : pourquoi le callback doit rester synchrone

C'est pour cela que le code passé en callback doit être SYNCHRONE : le navigateur a besoin de savoir exactement quand l'état "après" est prêt à être capturé.

Piège fréquent

Passer une fonction async ou contenant un appel réseau à document.startViewTransition() casse la capture : le navigateur prend sa "photo après" avant que les données ne soient arrivées. Préparez toutes les données AVANT d'appeler startViewTransition, et ne mettez dans le callback que la mise à jour synchrone du DOM.

Étape 5 : l'effet le plus impressionnant, le morphing

Au-delà d'un simple fondu global, view-transition-name isole UN élément précis pour qu'il bénéficie de sa propre transition individuelle.

Étape 6 : comment ce morphing se déclenche

Si ce même nom est réutilisé sur l'élément correspondant dans la nouvelle vue, le navigateur calcule automatiquement une interpolation fluide de position et de taille entre les deux.

Un dernier réflexe, la compatibilité

Il reste un bon réflexe à prendre : toujours vérifier if (!document.startViewTransition) avant de l'utiliser, et appliquer le changement directement sans animation sinon.

Pseudo-élémentRôle
::view-transition-old(root)capture de l'état "avant"
::view-transition-new(root)capture de l'état "après"
view-transition-name sur un élémentisole cet élément dans sa propre transition (morphing)

Et ensuite ?

Une fois ces transitions natives comprises, la prochaine étape va encore plus loin dans l'extension du moteur de rendu avec CSS Houdini.

Commandes & code

View Transitions API

Transitions animées natives entre deux états du DOM (ou deux pages), sans librairie tierce.

js
// Transition SPA : anime automatiquement la différence entre l'état avant/après
function changerVue(nouvelEtat) {
    if (!document.startViewTransition) {
        // navigateur sans support : appliquer directement, sans animation
        appliquerEtat(nouvelEtat);
        return;
    }

    document.startViewTransition(() => {
        // le callback DOIT être synchrone : le navigateur capture un "avant"
        // (screenshot), exécute ce callback, puis capture un "après"
        appliquerEtat(nouvelEtat);
    });
}

function appliquerEtat(etat) {
    document.querySelector("#contenu").innerHTML = etat.html;
}
css
/* Par défaut : simple fondu enchaîné (cross-fade) entre l'avant et l'après */
/* Personnalisation via les pseudo-éléments générés automatiquement */
::view-transition-old(root) {
    animation: disparition 0.3s ease-out;
}
::view-transition-new(root) {
    animation: apparition 0.3s ease-in;
}

@keyframes disparition {
    to { opacity: 0; }
}
@keyframes apparition {
    from { opacity: 0; }
}
html
<!-- view-transition-name : isole un élément dans SA PROPRE transition,
     avec un effet de "morphing" fluide entre positions/tailles -->
<img class="miniature" src="/img/produit-1.jpg" style="view-transition-name: image-produit">
js
// Transition d'une vignette vers une vue détail : morphing fluide automatique
document.querySelector(".miniature").addEventListener("click", (e) => {
    if (!document.startViewTransition) {
        ouvrirDetail();
        return;
    }

    document.startViewTransition(() => {
        ouvrirDetail(); // la nouvelle vue doit réutiliser le MÊME view-transition-name
    });
});
css
/* Transition différente pour un élément nommé spécifiquement */
::view-transition-old(image-produit),
::view-transition-new(image-produit) {
    animation-duration: 0.5s;
    /* le navigateur calcule seul l'interpolation de position/taille entre
       les deux états -- effet "shared element transition" sans calcul manuel */
}

/* Multi-page (MPA) : activer les transitions entre deux navigations complètes */
@view-transition {
    navigation: auto;
}

Résumé

  • document.startViewTransition(callback) capture un avant/après et anime la différence automatiquement.
  • Le callback passé doit rester synchrone : c'est lui qui produit l'état "après" que le navigateur capture.
  • view-transition-name isole un élément pour un effet de morphing fluide entre deux positions/tailles.
  • @view-transition { navigation: auto; } active les transitions natives entre pages en navigation multi-page (MPA).

Exercices pratiques

1 disponible
1

Mission : un morphing de galerie qui casse à cause d'un appel réseau

Objectif : Diagnostiquer une capture de transition ratée à cause d'un callback asynchrone, et configurer un morphing d'élément nommé.

Contexte

Sur galerie.js, au clic sur une vignette, le code appelle document.startViewTransition(async () => { const details = await fetch('/api/produit/' + id); afficherDetail(details); }). Résultat observé : la transition capture une "photo après" vide ou incohérente, et l'effet de morphing attendu entre la vignette et la vue détail ne se produit jamais correctement, malgré la présence d'un view-transition-name déjà posé sur l'image.

Résoudre l’exercice →