TransitionsGratuit

Crossfade Transition

Deux états superposés au même endroit : l'un s'efface pendant que l'autre apparaît, en 0,8 s, sur un simple basculement de classe — ni mouvement ni couleur intermédiaire, les deux images se mélangent pendant le passage. CSS + 0,9 Ko de JavaScript, clic, Entrée ou Espace, fondu raccourci à 0,15 s si l'utilisateur réduit les animations.

CSSCrossfadePremium

Mis à jour le

État A
Page d'accueil
Cliquez pour basculer
Survolez ou cliquez la scène pour interagir

Cet effet est gratuit — la catégorie Transitions en contient 52 au total, dont 9 gratuits. Effect.Labs regroupe 840 effets vanilla. Découvrir la catégorie →

Exemples d'usage

Piste Rouge · ven. 15 janv. · 14:05
EN DIRECT
Webcam 3alt. 1 650 m
Neige110 cm · −6 °C
Piste Rouge · ouverte1,2 km, damée ce matin, éclairée à la nuit
Ski nocturnemar. et ven., 17 h 30 – 20 h 30 : dès 17 h 30, la caméra montre la piste éclairée

① Webcam de jour vers webcam de nuit — site d'une station de ski

QuandUn vendredi de janvier, à 17 h 30, un skieur du village ouvre la webcam 3 pour savoir si la nocturne vaut le coup : la piste Rouge en plein jour s'efface dans la même piste, éclairée pour le ski du soir.
PourquoiMême cadre, même géométrie : le fondu superpose les deux images et ne fait apparaître que ce qui change, la lumière.
RéglagesCadre agrandi à la taille de la vue webcam ; les deux états dessinent le même paysage (sommets, pente, sapins, piquets et lampadaires aux mêmes coordonnées), seules les couleurs changent : ciel étoilé, piste dorée et halos des lampadaires dans l'état B ; heure incrustée dans chaque état.
Montures optiques · Acétate 289 € Touchez la photo : seule / portée

Monture Anna — écaille miel

Acétate italien poli à la main, charnières 5 barils. Taille 50 □ 20 – 145, fabriquée dans le Jura.

Réserver un essayage

② Monture seule vers monture portée — fiche produit d'un lunetier artisanal

QuandUne cliente qui hésite sur la monture Anna touche la photo : l'écaille miel posée sur fond blanc se fond dans la même monture portée sur un visage, à la même place.
PourquoiLe fondu sans mouvement garde les deux images au même endroit : l'œil compare la forme de la monture seule et sur le visage.
RéglagesLes lunettes occupent exactement la même place dans les deux états (même bloc .k695-glasses), le visage et le fond vert d'eau n'existent que dans B ; verres presque opaques dans A, transparents dans B pour laisser voir les yeux.
SÉJOURCH. 1CH. 2SDBENTRÉE 7,80 m4,20 m

T3 · 64,2 m²

Bâtiment B · 3e étage · lot B12

Balcon sud 7 m² · livraison 3e trim. 2027

  • Séjour 24,6 m²
  • Chambre 1 11,2 m²
  • Chambre 2 10,4 m²

③ Plan nu vers plan meublé — configurateur d'un promoteur immobilier

QuandUn couple qui vise le lot B12 active « Meubler » pour se projeter : le plan coté du T3 laisse place au même plan, avec canapé, lits et passages entre les meubles.
PourquoiLes murs ne bougent pas, seuls les meubles apparaissent : le fondu montre l'aménagement sans faire perdre les repères.
RéglagesMurs, portes, fenêtres, noms des pièces et cotes répétés à l'identique dans les deux états, meubles seulement dans B ; un interrupteur « Meubler » à côté du plan déclenche le même basculement que le clic sur le plan et suit son état (aria-pressed).

Comment ça marche

La scène .crossfade-stage (250 px de haut, fond #1a1a24, contenu centré) porte un cadre .crossfade-frame de 280 × 180 px, coins de 16 px, overflow: hidden. Dedans, deux calques .crossfade-state en position: absolute; inset: 0 occupent exactement la même place : l'état A (dégradé indigo vers violet, opacité 1) et l'état B, posé au-dessus dans le HTML (dégradé rose vers magenta, opacité 0). Les deux ont la même règle transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1).

Tout le passage tient dans deux règles : .crossfade-frame.active .crossfade-state-a { opacity: 0 } et .crossfade-frame.active .crossfade-state-b { opacity: 1 }. Le script pose ou retire .active au clic, à Entrée ou à Espace sur chaque .crossfade-frame de la page, met à jour aria-pressed et masque aux lecteurs d'écran l'état caché (aria-hidden). L'état B reste affiché tant qu'on ne rappuie pas ; le second appui refait le fondu en sens inverse. Mesuré dans Chromium 151 et Firefox 153 : 250 ms après le clic, A est à 0,63 et B à 0,37 ; à 1,1 s, A à 0 et B à 1 ; trois secondes plus tard, toujours B ; le second clic ramène A à 1. Même résultat dans WebKit 26.5.

Le fondu n'est pas une surimpression parfaite : à mi-parcours, chaque calque est à environ 50 %, donc près d'un quart du fond de la scène transparaît (0,37 × 0,63 = 0,23 au relevé de 250 ms). Sur deux images claires, on voit un léger creux sombre au milieu du passage ; c'est ce qui rend ce fondu doux, et la FAQ dit comment le supprimer. Le code ne dépend ni de la page ni d'un id : plusieurs cadres cohabitent, chacun avec son état, et le script n'expose rien sur window. Une variante de ce fondu existe aussi dans la catégorie.

Accessibilité

  • Mouvement réduit : sous prefers-reduced-motion: reduce, la durée du fondu passe de 0,8 s à 0,15 s. Le fondu ne déplace rien, il est donc gardé, seulement raccourci (mesuré : passage terminé en moins de 260 ms dans Chromium et Firefox).
  • Clavier et lecteurs d'écran : le cadre porte role="button", tabindex="0" et aria-pressed ; Entrée et Espace basculent comme un clic (mesuré dans les deux moteurs). L'état caché reçoit aria-hidden="true" : le nom lu du bouton est le texte de l'état visible. Un contour de 2 px apparaît au focus clavier (:focus-visible).
  • Ne rien cacher d'important dans le passage : pendant 0,8 s les deux textes se superposent et aucun n'est lisible. Ne mettez pas d'information qui n'existerait qu'au milieu du fondu ; les deux états doivent se suffire.
  • Contraste : le texte blanc tient sur les deux dégradés de démonstration ; si vous mettez des photos, ajoutez un voile sombre derrière le texte, surtout au milieu du fondu où les deux images se mélangent.

Compatibilité navigateur

CSS (opacity, transition, inset, :focus-visible) + 0,9 Ko de JavaScript, aucune dépendance. Mesuré dans Chromium 151, Firefox 153 et WebKit 26.5 : bascule, état B tenu, retour au second clic ; clavier et mouvement réduit mesurés dans Chromium et Firefox. La propriété inset fixe le plancher (Chrome 87, Firefox 66, Safari 14.1) ; :focus-visible et le flou de l'icône (backdrop-filter) sont des finitions qui disparaissent sans casser l'effet sur un navigateur plus ancien.

Chrome 87+✓ Complet
Firefox 66+✓ Complet
Safari 14.1+✓ Complet
Edge 87+✓ Complet
Mobile iOS 14.5+✓ Complet
Android Chrome 87+✓ Complet

Sans JavaScript, l'état A reste affiché et le cadre ne réagit pas. Sur un navigateur qui ignore inset, remplacez-le par top: 0; right: 0; bottom: 0; left: 0. Sans backdrop-filter, l'icône garde son fond blanc à 20 %, sans flou.

Le code

Copiez les trois blocs dans votre page. Aucune dépendance.

HTML
<div class="crossfade-stage">
  <div class="crossfade-frame" role="button" tabindex="0" aria-pressed="false">
    <div class="crossfade-state crossfade-state-a">
      <div class="crossfade-icon" aria-hidden="true">&#9733;</div>
      <div>
        <div style="font-size: 1rem; font-weight: 800;">État A</div>
        <div style="font-size: 0.65rem; opacity: 0.7; margin-top: 2px;">Page d'accueil</div>
      </div>
    </div>
    <div class="crossfade-state crossfade-state-b" aria-hidden="true">
      <div class="crossfade-icon" aria-hidden="true">&#9829;</div>
      <div>
        <div style="font-size: 1rem; font-weight: 800;">État B</div>
        <div style="font-size: 0.65rem; opacity: 0.7; margin-top: 2px;">Page profil</div>
      </div>
    </div>
  </div>
  <span class="crossfade-hint">Cliquez pour basculer</span>
</div>
CSS
.crossfade-stage,
.crossfade-stage *,
.crossfade-stage *::before,
.crossfade-stage *::after {
  box-sizing: border-box
}

.crossfade-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: #fff;
  font-family: sans-serif
}

.crossfade-hint {
  position: absolute;
  bottom: 12px;
  left: 50%;
  transform: translateX(-50%);
  font-size: .65rem;
  color: rgba(255, 255, 255, .35);
  text-transform: uppercase;
  letter-spacing: 2px;
  white-space: nowrap;
  pointer-events: none
}

.crossfade-frame {
  width: 280px;
  height: 180px;
  border-radius: 16px;
  position: relative;
  overflow: hidden;
  cursor: pointer
}

.crossfade-frame:focus-visible {
  outline: 2px solid #f9a8d4;
  outline-offset: 4px
}

.crossfade-state {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: 1px;
  transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 16px
}

.crossfade-state-a {
  background: linear-gradient(135deg, #6366f1, #8b5cf6, #a855f7);
  opacity: 1
}

.crossfade-state-b {
  background: linear-gradient(135deg, #f43f5e, #ec4899, #d946ef);
  opacity: 0
}

.crossfade-frame.active .crossfade-state-a {
  opacity: 0
}

.crossfade-frame.active .crossfade-state-b {
  opacity: 1
}

.crossfade-icon {
  width: 50px;
  height: 50px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.2);
  margin-right: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  backdrop-filter: blur(10px)
}

/* Mouvement réduit : le fondu reste (aucun déplacement), raccourci à 0,15 s */
@media (prefers-reduced-motion: reduce) {
  .crossfade-state {
    transition-duration: .15s
  }
}
JavaScript (fx-0695)
(function() {
  /* fx-0695 : Crossfade Transition — chaque .crossfade-frame de la page bascule entre l'état A et l'état B
     (clic, Entrée ou Espace) et reste sur l'état atteint ; l'action suivante fait le chemin inverse. */
  document.querySelectorAll('.crossfade-frame').forEach(function(frame) {
    var a = frame.querySelector('.crossfade-state-a');
    var b = frame.querySelector('.crossfade-state-b');
    function toggle() {
      var on = frame.classList.toggle('active');
      frame.setAttribute('aria-pressed', on ? 'true' : 'false');
      if (a) a.setAttribute('aria-hidden', on ? 'true' : 'false');
      if (b) b.setAttribute('aria-hidden', on ? 'false' : 'true');
    }
    frame.addEventListener('click', toggle);
    frame.addEventListener('keydown', function(e) {
      if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); }
    });
  });
})();

Personnaliser

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

Option / propriétéDéfautEffet
Durée (CSS — transition de .crossfade-state) 0,8 s 0,4 s pour un changement d'onglet vif, 1,2 s pour une vitrine contemplative. Au-delà d'1,5 s, l'utilisateur reclique pendant le fondu.
Courbe (CSS — cubic-bezier(0.4, 0, 0.2, 1)) démarrage doux, fin douce linear donne un fondu régulier ; ease-out fait apparaître B plus vite au début.
Contenu des états (HTML — .crossfade-state-a, -b) icône + deux lignes de texte sur un dégradé Mettez-y n'importe quel contenu de même taille : photo, plan, carte. Plus les deux contenus partagent la même géométrie, plus le fondu montre clairement ce qui change.
Taille du cadre (CSS — .crossfade-frame) 280 × 180 px, coins de 16 px width: 100%; aspect-ratio: 16/9 pour une image pleine largeur ; le cadre garde overflow: hidden pour que les coins arrondis coupent les deux états.
Hauteur de la scène (CSS — .crossfade-stage) 250 px, fond #1a1a24 Retirez la hauteur et le fond si le cadre s'insère dans votre propre mise en page ; la scène ne sert qu'à centrer la démo.

FAQ

Pourquoi voit-on un léger creux sombre au milieu du fondu ?

Les deux calques passent par 50 % en même temps : à cet instant, le fond de la scène transparaît pour environ un quart. Si l'état B est opaque (une photo, un fond plein), gardez l'état A à opacité 1 et ne faites varier que B : .crossfade-frame.active .crossfade-state-a { opacity: 1 }. B, posé au-dessus, recouvre A en fondu sans creux. Gardez la version croisée quand les états ont de la transparence, sinon A resterait visible sous B.

Est-ce l'API View Transitions ?

Non. C'est une transition CSS d'opacité sur deux calques déjà présents dans la page, qui marche partout depuis longtemps. L'API View Transitions (document.startViewTransition) produit un fondu comparable entre deux états du DOM sans garder les deux contenus en permanence, mais demande un navigateur récent (Chrome 111, Safari 18, Firefox 144) et un repli ailleurs. Pour basculer entre deux contenus connus à l'avance, les deux calques suffisent.

Comment enchaîner plus de deux états ?

Ajoutez autant de calques .crossfade-state que d'états, tous à opacité 0, et une classe is-on qui met l'actif à 1. Au clic, retirez is-on de l'état courant et posez-la sur le suivant : la même transition fait le fondu. Gardez aria-hidden sur tous les états sauf l'actif.