Transitions✨ Premium

Cross-Document Page Morph

Deux vraies pages HTML et un lien ordinaire : la vignette de la page liste grandit jusqu'à devenir l'en-tête de la page article pendant que le navigateur change de page — @view-transition { navigation: auto; } et le même view-transition-name des deux côtés, zéro JavaScript, morph de 0,5 s à l'aller comme au bouton retour, navigation normale là où le navigateur ne sait pas faire.

View TransitionsMPA0 JS

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Transitions comprend 52 effets, dont 9 gratuits. Découvrir la catégorie →

3 exemples d'usage

Sommaire vers poème — site statique d'une revue de poésie — Cross-Document Page Morph exemple 1

① Sommaire vers poème — site statique d'une revue de poésie

QuandLe lecteur parcourt le sommaire du numéro d'automne et clique sur un poème : la page sommaire.html laisse place à la page du poème, après un simple lien.
PourquoiLe site reste fait de pages statiques ; l'illustration du sommaire morphe vers l'en-tête du poème sans framework ni JavaScript, et le bouton retour ramène l'image dans le sommaire.
RéglagesTrois vignettes de 56 px de haut en bas du sommaire, en-tête de 104 px sur la page du poème ; un nom par poème (x8a-ill-maree, -seigles, -oiseaux) ; la page poeme.html garde les trois poèmes et l'ancre (#maree) choisit lequel s'affiche, comme le code vendu ; illustrations en dégradés CSS, police Georgia sur papier crème.
Annuaire des praticiens vers page d'une sage-femme — site d'une maison de santé — Cross-Document Page Morph exemple 2

② Annuaire des praticiens vers page d'une sage-femme — site d'une maison de santé

QuandUne patiente cherche à qui s'adresser pour son suivi de grossesse : dans l'annuaire, elle ouvre la page de la sage-femme, avec ses horaires et le bouton de rendez-vous.
PourquoiLe portrait passe d'une page à l'autre : l'impression d'une application, avec des pages que n'importe quel hébergement sert, et une adresse à partager pour chaque praticienne.
RéglagesPortrait au format 3:4 dans la carte de l'annuaire et en 132 × 176 px sur la page de la praticienne : mêmes proportions, le morph agrandit sans recadrer ; une page par praticienne (sage-femme.html), sans ancre ; seul ce portrait porte un view-transition-name, les autres cartes restent immobiles dans le fondu.
Liste des circuits vers page d'un circuit — site d'un loueur de vélos électriques — Cross-Document Page Morph exemple 3

③ Liste des circuits vers page d'un circuit — site d'un loueur de vélos électriques

QuandLe visiteur compare les circuits au départ de la boutique et ouvre « Gorges et lavandes » : distance, dénivelé, durée, batterie conseillée et réservation.
PourquoiLa carte du circuit grandit en en-tête de la page suivante et garde le visiteur dans son repère ; sans support du navigateur, la navigation reste normale.
RéglagesCarte en SVG en ligne avec preserveAspectRatio="xMidYMid slice" : 118 px de haut dans la carte de la liste, 124 px en en-tête de 500 px de large ; le recadrage object-fit: cover du code vendu évite toute déformation pendant le morph ; page dédiée gorges-et-lavandes.html ; carte du circuit mise en avant par un liseré orange.

Comment ça marche

Le code tient en deux fichiers à poser côte à côte : page-liste.html (trois cartes, chacune un vrai lien <a href="page-article.html#natif">) et page-article.html (trois <article>). Les deux pages ouvrent leur feuille de style par la même règle, @view-transition { navigation: auto; } : c'est l'accord des deux côtés qui autorise le navigateur à animer le passage. Au clic, il photographie la page liste, charge la page article, cherche dans les deux les éléments qui portent le même view-transition-name — la vignette .xdvt-thumb--natif et l'en-tête .xdvt-hero--natif s'appellent tous deux xdvt-hero-natif — et fait glisser et grandir l'un vers l'autre en 0,5 s, courbe cubic-bezier(.2, .8, .2, 1) ; le reste de la page passe en fondu enchaîné. Aucune ligne de JavaScript : le champ JS est vide, tout est dans le CSS.

La vignette est large et basse (110 px de haut dans une carte d'au moins 200 px), l'en-tête plus haut (220 px sur toute la largeur) : sans précaution, chaque image garderait ses proportions et déborderait dessus et dessous pendant le morph. ::view-transition-old(*) et ::view-transition-new(*) reçoivent donc block-size: 100% et object-fit: cover, et ::view-transition-image-pair(*) un overflow: clip : chaque image remplit le cadre qui grandit, recadrée. Chaque carte a son propre nom (xdvt-hero-natif, -zero, -mpa), car un nom doit être unique dans une page : deux éléments visibles avec le même nom, et Chromium annule tout le morph (mesuré, message « Unexpected duplicate view-transition-name » dans la console). Sur la page article, les trois en-têtes portent les trois noms sans conflit, parce que seul l'article affiché est photographié ; les deux vignettes qui n'ont pas de partenaire s'effacent sur place pendant le fondu.

La page article porte les trois articles et l'ancre choisit lequel s'affiche : .xdvt-article est masqué, le premier s'affiche par défaut, :target affiche celui que vise l'adresse (#zero) et :has() masque alors le premier. C'est ce qui permet de livrer l'effet en deux fichiers seulement. Sur un vrai site, faites une page par article (article-natif.html…) : un seul <article>, plus de règles :target, chaque page a son titre et son adresse,. Le retour n'a pas besoin de code : le lien « ← Retour à la liste » comme le bouton retour du navigateur rejouent le morph dans l'autre sens, l'en-tête redevient vignette (mesuré dans Chromium 151 et WebKit 26.5). Les pages doivent être servies en HTTP ou HTTPS, depuis la même origine : un navigateur qui ne connaît pas ces transitions ignore la règle et charge la page comme d'habitude.

Accessibilité

  • Mouvement réduit : les deux pages déclarent @media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }. Mesuré sous émulation dans Chromium 151 et WebKit 26.5 : aucune animation, la page article remplace la liste d'un coup, à l'aller comme au retour.
  • Vraie navigation : chaque passage est un changement de page ordinaire. Le lecteur d'écran annonce le titre de la nouvelle page, le focus repart du haut du document, l'historique, le bouton retour, l'ouverture dans un nouvel onglet et le partage de l'adresse marchent sans rien gérer. La photo du morph est purement visuelle. Donnez à chaque page article un <title> qui nomme l'article : la version à ancres en a un seul pour les trois (« Le carnet — article »), une raison de plus pour faire une page par article.
  • Clavier : les cartes sont de vrais liens, atteignables à la tabulation (dans Safari, Option + Tab ou le réglage « Tab parcourt tous les éléments »), avec un contour blanc de 2 px au focus (:focus-visible). Entrée sur une carte joue le même morph qu'un clic (mesuré dans Chromium et WebKit).
  • Contraste : le texte secondaire des cartes (#a3a9c9 sur #161b36) est à 7,29:1, le surtitre (#8a90b0 sur #0d1124) à 5,96:1, le texte de l'article à 11,9:1. Les dégradés des vignettes ne portent pas de texte ; si vous y écrivez, du blanc descend à 3,09:1 sur le bleu #6d8bff et à 1,25:1 sur le vert menthe #5cffd8 : posez le texte sur un bandeau sombre.

Compatibilité navigateur

CSS seul : @view-transition, view-transition-name, les pseudo-éléments ::view-transition-*, :target et :has() ; aucun JavaScript, aucune dépendance. Mesuré avec Playwright, pages servies en HTTP depuis la même origine : morph à l'aller, au lien retour et au bouton retour du navigateur dans Chromium 151 et WebKit 26.5 (aussi dans une iframe de même origine) ; Firefox 153 change de page normalement, sans animation ni erreur, bien qu'il connaisse déjà les transitions dans une même page. Pas de morph entre deux origines différentes (mesuré entre localhost et 127.0.0.1), ni dans une iframe sandbox sans allow-same-origin. En fichiers ouverts en double-clic (file://), WebKit ne joue pas le morph et Chromium l'a joué dans notre test : ne vous y fiez pas, testez avec un petit serveur local. Support public des transitions entre documents : Chrome et Edge 126, Safari 18.2.

Chrome 126+✓ Complet
Edge 126+✓ Complet
Safari 18.2+✓ Complet
Firefox (153 mesuré)✓ Navigation normale, sans morph
Mobile iOS 18.2+ / Android Chrome 126+✓ Complet
Navigateurs plus anciens✓ Navigation normale, sans morph

Un navigateur qui ne connaît pas @view-transition ignore la règle : le lien charge la page article comme n'importe quel lien, avec le même contenu, la même adresse et le même historique. Même chose sous mouvement réduit (navigation: none), entre deux origines différentes, ou si deux éléments visibles d'une page portent le même nom. Rien ne casse, seul le morph manque.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :

index.html — structure
<!-- page-liste.html : @view-transition { navigation: auto; } dans le style -->
<body class="xdvt-page">
  <main class="xdvt-wrap">
    <p class="xdvt-h">…</p>
    <h1 class="xdvt-title">…</h1>
    <div class="xdvt-grid">
      <a class="xdvt-card" href="page-article.html#natif">
        <span class="xdvt-thumb xdvt-thumb--natif"></span>
        <span class="lbl">…</span>
        <span class="meta">…</span>
      </a> … (3 cartes : #natif, #zero, #mpa)
    </div>
  </main>
</body>

<!-- page-article.html : même règle, mêmes noms sur les en-têtes -->
<body class="xdvt-page">
  <main class="xdvt-wrap">
    <p class="xdvt-h">…</p>
    <a class="xdvt-back" href="page-liste.html">← …</a>
    <article class="xdvt-article" id="natif">
      <div class="xdvt-hero xdvt-hero--natif"></div>
      <h1>…</h1>
      <p>…</p>
    </article> … (3 articles : natif, zero, mpa)
  </main>
</body>
Débloquer le code complet — 9,90 € TTC/mois

Le code complet HTML + CSS + JS de Cross-Document Page Morph, prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
Durée et courbe (CSS — ::view-transition-group(*)) 0,5 s, cubic-bezier(.2, .8, .2, 1) 0,3 s donne un passage vif, au-delà de 0,8 s on attend la page. Le * vise tous les groupes, fondu de la page compris ; pour régler un seul élément, nommez-le : ::view-transition-group(xdvt-hero-natif).
Éléments partagés (CSS — view-transition-name) un nom par carte : xdvt-hero-natif, -zero, -mpa Même nom sur la vignette et sur l'en-tête de l'article qu'elle ouvre, unique dans chaque page. Pour faire aussi glisser le titre, donnez un second nom (xdvt-title-natif) au libellé de la carte et au <h1> de l'article.
Recadrage pendant le morph (CSS — ::view-transition-old(*), ::view-transition-new(*)) block-size: 100%, object-fit: cover, image-pair en overflow: clip Sans ces règles, chaque image garde ses proportions et déborde du cadre quand la vignette et l'en-tête n'ont pas la même forme. object-fit: contain montre l'image entière, avec des bandes vides.
Fondu du reste de la page (CSS — ::view-transition-old(root), ::view-transition-new(root)) fondu enchaîné du navigateur, 0,5 s animation: none sur les deux supprime le fondu : le reste de la page change d'un coup et seul l'élément partagé bouge. Gardez l'en-tête du site identique sur les deux pages : il paraît alors immobile.
Mouvement réduit (CSS — @media (prefers-reduced-motion: reduce)) @view-transition { navigation: none; } Navigation sans aucune animation. Pour un fondu très court à la place, gardez navigation: auto dans ce bloc et réglez ::view-transition-group(*) à animation-duration: .15s.
Choix de l'article (CSS — :target et :has()) une page article qui porte trois articles, le premier par défaut Sur un vrai site, une page par article : un seul <article>, les quatre règles .xdvt-article supprimées, le lien devient article-natif.html. Les noms ne changent pas.

FAQ

Le navigateur n'anime le passage qu'entre deux pages de la même origine (même protocole, même domaine, même port), servies en HTTP ou HTTPS. Ouvertes en file://, les pages n'ont pas d'origine fiable : WebKit ne joue pas le morph, Chromium l'a joué dans notre test, mais rien ne le garantit. Pour tester, lancez un petit serveur dans le dossier (python3 -m http.server, puis http://localhost:8000/page-liste.html) ou passez par celui de votre éditeur. Même règle en ligne : pas de morph entre www. et le domaine nu, ni dans une iframe sandbox sans allow-same-origin.
La même API du navigateur, deux usages. View Transitions Page Reveal anime une grille et une vue détail dans un seul document, avec document.startViewTransition() et 2,5 Ko de JavaScript : utile dans une application d'une seule page, et elle joue aussi dans Firefox. Cross-Document Page Morph anime entre deux vraies pages, avec deux règles CSS et aucun script : chaque page garde son adresse, son historique et son référencement, mais Firefox (153 mesuré) se contente pour l'instant d'une navigation normale. Choisissez celui-ci pour un site fait de pages, l'autre pour une interface qui ne recharge pas.
Non. Firefox 153 lit déjà view-transition-name et sait animer dans une même page ; il ignore seulement @view-transition entre deux documents, sans erreur. Le jour où il l'applique, les mêmes deux fichiers morpheront chez lui comme dans Chrome et Safari.