Shared Element
Un seul élément, jamais copié, glisse d'un emplacement à l'autre en 0,8 s avec un dépassement de 17 px avant de se poser, grossit de 15 % et passe du rose au violet : l'objet reste le même pendant que sa place change. Une transition CSS sur transform, posée sur deux positions connues d'avance — 0,6 Ko de JavaScript pour la bascule, arrivée directe si l'utilisateur réduit les animations.
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



Comment ça marche
La scène .shared-container mesure 300 × 200 px et range côte à côte deux emplacements .shared-slot de 110 × 130 px, bordés de pointillés, à 30 px d'écart. L'élément partagé .shared-ball (rond de 60 px, dégradé #e11d48 → #f43f5e, ombre rose) n'appartient à aucun des deux : il est en position absolue dans la scène, à 25 px du bord gauche. Toute la zone .shared-trigger est un bouton (role="button", tabindex="0") : un clic, Entrée ou Espace bascule la classe .active sur la scène et met à jour aria-pressed. Chaque zone de la page a son propre écouteur, rien n'est exposé sur window.
Avec .active, l'élément reçoit transform: translateX(190px) scale(1.15) (190 px = 300 px de scène − 85 − 25), un dégradé violet #7c3aed → #a78bfa et une ombre violette. La transition de 0,8 s suit cubic-bezier(.34, 1.56, .64, 1), une courbe qui dépasse 1 : mesuré toutes les 100 ms dans Chromium 151 et Firefox 153, l'élément passe à 116, 176, 214 puis 228 px, dépasse sa place de 17 px vers 400-500 ms, revient et se pose à 211 px à 800 ms. Le déplacement passe par transform, que le navigateur compose sans recalculer la mise en page ; l'ombre change de couleur pendant le trajet, mais le dégradé, qui ne s'interpole pas, bascule dès le clic. Un second clic joue le chemin inverse avec le même rebond.
C'est une technique à la main : les deux positions sont connues d'avance et écrites dans le CSS, l'élément ne change jamais de parent dans le DOM. L'API View Transitions fait autre chose : elle photographie la page avant et après un changement du DOM et interpole entre les deux images (voir View Transitions Page Reveal). Ici, aucun instantané : c'est le vrai élément qui se déplace, avec son texte, ses états de survol et son focus, et cela fonctionne dans tous les navigateurs qui connaissent les transitions CSS. La contrepartie : si l'arrivée dépend de la mise en page (une carte qui change de liste), il faut mesurer les positions en JavaScript, comme le décrit la FAQ.
Accessibilité
- Clavier : la zone est un bouton atteignable à la tabulation ; Entrée et Espace basculent comme le clic (mesuré dans Chromium et Firefox),
aria-pressedpasse àtrue, et un contour blanc de 2 px marque le focus. Sonaria-label(« Déplacer l'élément vers l'autre zone ») dit l'action ; remplacez-le par la vôtre (« Marquer la commande comme expédiée »). - Mouvement réduit : sous
prefers-reduced-motion, la transition est retirée et l'élément est dans l'autre zone dès l'image suivante — mesuré : 211 px 60 ms après le clic, sans dépassement. - Changement d'état : le déplacement se voit mais ne s'entend pas. Si l'emplacement porte un sens (statut, équipe), écrivez-le aussi dans le texte de l'élément ou annoncez-le dans une zone
aria-live: un lecteur d'écran ne perçoit quearia-pressed. - Contraste : « GO » en blanc donne 4,7:1 sur le rouge
#e11d48mais 3,7:1 sur le rose clair et 2,7:1 sur#a78bfa; gardez un texte court et gras, ou foncez la fin des dégradés. Les étiquettes des zones (blanc à 30 %, 2,6:1) et l'indication du bas (3,1:1) sont décoratives : ne leur confiez pas d'information.
Compatibilité navigateur
Transitions CSS sur transform, box-shadow et background, et une quinzaine de lignes de JavaScript, aucune dépendance. Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : même trajet de 190 px, même dépassement, même arrivée à l'échelle 1,15, même retour au second clic ; arrivée directe sous mouvement réduit. Seul le dégradé de fond ne s'interpole pas (aucun navigateur n'anime background-image) : il bascule au départ.
Sans JavaScript, l'élément reste dans la première zone et le clic ne fait rien. Avec le mouvement réduit, il change de zone sans trajet. Sans transitions CSS (navigateurs très anciens), il saute d'une zone à l'autre.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :
<div class="shared-root">
<div class="shared-trigger" role="button" tabindex="0" aria-pressed="false" aria-label="…">
<div class="shared-container">
<div class="shared-slot"><span class="shared-slot-label">Zone A</span></div>
<div class="shared-slot"><span class="shared-slot-label">Zone B</span></div>
<div class="shared-ball">GO</div>
</div>
<span class="shared-hint">Cliquez pour basculer</span>
</div>
</div>
Le code complet HTML + CSS + JS de Shared Element, 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éfaut | Effet |
|---|---|---|
Trajet (CSS — translateX(190px)) |
190 px vers la droite | Calculé pour la scène de 300 px. translateY(-80px) donne un trajet vertical ; translate(190px, 40px) une diagonale. Le dépassement vaut environ 9 % du trajet : prévoyez la marge correspondante au bord. |
Courbe et durée (CSS — transition: .8s cubic-bezier(.34, 1.56, .64, 1)) |
0,8 s, dépassement puis retour | cubic-bezier(.2, .8, .2, 1) arrive sans dépasser ; 0,5 s pour un déplacement court, au-delà de 1 s le geste paraît lent. |
Grossissement à l'arrivée (CSS — scale(1.15)) |
×1,15 | scale(1) garde la taille ; un élément qui change d'importance (sélectionné, mis en avant) peut aller à 1,3. |
Couleurs (CSS — background et box-shadow de .shared-ball) |
rose #e11d48 → violet #7c3aed |
L'ombre glisse d'une couleur à l'autre, le dégradé bascule au départ. Pour une couleur qui change en route, utilisez background-color uni (il s'interpole). |
Forme de l'élément (CSS — .shared-ball) |
rond de 60 px | Une carte, un badge, une image : changez width, height et border-radius, puis recalculez le trajet pour qu'il arrive dans le second emplacement. |
FAQ
document.startViewTransition, view-transition-name) photographie la page avant et après un changement du DOM et anime entre les deux images ; c'est ce que fait View Transitions Page Reveal (fx-0786). Shared Element anime le vrai élément avec une transition CSS sur transform, entre deux positions écrites dans la feuille de style. Avantages : fonctionne partout, garde le texte sélectionnable et le focus pendant le trajet. Limite : l'élément ne change pas de parent, les positions doivent être connues.var first = el.getBoundingClientRect()), déplacez-le dans le DOM (colonneB.appendChild(el)), mesurez la nouvelle (last), appliquez sans transition el.style.transform = 'translate(' + (first.left - last.left) + 'px, ' + (first.top - last.top) + 'px)' pour le remettre visuellement à son point de départ, puis, à l'image suivante (requestAnimationFrame), remettez transform à zéro avec la transition de cet effet. L'élément glisse vers sa nouvelle place, avec le même dépassement.background-image), et les navigateurs n'interpolent pas un dégradé vers un autre : la valeur bascule au début de la transition. L'ombre, elle, est une couleur simple et passe du rose au violet pendant tout le trajet. Pour une couleur qui change en route, remplacez le dégradé par background-color, ou superposez un pseudo-élément ::before violet dont l'opacité passe de 0 à 1.