Comment animer des éléments au défilement ?

Les animations au scroll révèlent, déplacent ou transforment le contenu pendant que l'on fait défiler la page. Il existe deux approches : IntersectionObserver en JavaScript, qui ajoute une classe quand un élément entre à l'écran et fonctionne dans tous les navigateurs, et les animations CSS pilotées par le scroll (animation-timeline: scroll() ou view()), qui lient une animation à la position de défilement sans JavaScript.

Comment choisir, performances et accessibilité
  • Utilisez Fade Up ou Stagger Cards pour faire apparaître des sections, une Barre de progression de lecture sur les articles longs, Parallax ou le scrollytelling collant pour les pages qui racontent une histoire, et Vertical Snap pour des diapositives plein écran.
  • Les animations CSS pilotées par le scroll fonctionnent dans Chrome, Edge et Safari 26, mais pas encore dans Firefox : gardez le contenu visible sans elles.
  • N'animez que transform et opacity, et coupez les effets pour prefers-reduced-motion.
  • Fade Up, Barre de progression, Sticky Image Change et Vertical Snap font partie des effets gratuits avec leur code complet ; les autres sont inclus dans Premium.

Scroll Basics

20 effets fondamentaux de scroll et parallax.

Premier element

Apparait en montant avec un fondu

Deuxieme element

Animation progressive au scroll

Troisieme element

Utilise animation-timeline: view()

Quatrieme element

Chaque element s'anime individuellement

Cinquieme element

Tout en CSS, zero JavaScript

Scrollez ↓

Fade Up

Éléments qui apparaissent en montant avec un fondu progressif via animation-timeline: view().

CSSScrollFade
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="sdc-scroll-container">
    <div class="sb-fadeup-content">
      <div class="sb-fadeup-box"><h4>Premier element</h4><p>Apparait en montant avec un fondu</p></div>
      <div class="sb-fadeup-box"><h4>Deuxieme element</h4><p>Animation progressive au scroll</p></div>
      <div class="sb-fadeup-box"><h4>Troisieme element</h4><p>Utilise animation-timeline: view()</p></div>
      <div class="sb-fadeup-box"><h4>Quatrieme element</h4><p>Chaque element s'anime individuellement</p></div>
      <div class="sb-fadeup-box"><h4>Cinquieme element</h4><p>Tout en CSS, zero JavaScript</p></div>
    </div>
  </div>
  <span class="sdc-scroll-hint">Scrollez ↓</span>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.sb-fadeup-content {
  height: 900px;
  padding: 60px 20px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.sb-fadeup-box {
  padding: 24px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  text-align: center;
  opacity: 0;
  transform: translateY(60px);
  animation: sbFadeUp linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 50%;
}

.sb-fadeup-box h4 {
  font-size: 0.9rem;
  font-weight: 700;
  color: #fff;
  margin: 0 0 6px;
}

.sb-fadeup-box p {
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.5);
  margin: 0;
}

.sdc-scroll-container {
  width: 100%;
  height: 280px;
  overflow-y: auto;
  position: relative;
  scroll-behavior: smooth;
}

.sdc-scroll-container::-webkit-scrollbar {
  width: 4px;
}

.sdc-scroll-container::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.05);
}

.sdc-scroll-container::-webkit-scrollbar-thumb {
  background: rgba(139, 92, 246, 0.4);
  border-radius: 2px;
}

.sdc-scroll-hint {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.3);
  z-index: 5;
  pointer-events: none;
  animation: sdcHintPulse 2s ease-in-out infinite;
}

@keyframes sbFadeUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes sdcHintPulse {

  0%,
  100% {
    opacity: 0.3;
  }

  50% {
    opacity: 0.7;
  }
}
JavaScript
/* CSS pur — aucun JavaScript requis */

Scale In

Éléments qui grossissent depuis une taille réduite avec animation-timeline: view().

CSSScaleScroll

Slide In

Éléments glissant depuis la gauche et la droite en alternance via view().

CSSSlideScroll

Parallax

Effet de parallaxe ou l'arrière-plan bouge a vitesse différente via scroll(nearest).

CSSParallaxScroll

Progress Reveal

Texte qui se remplit progressivement avec un gradient animé par scroll(nearest) et @property.

CSSProgressGradient

Stagger Cards

Cartes apparaissant en cascade avec animation-delay incremental et view().

CSSStaggerCards

Horizontal Scroll

Défilement horizontal avec scroll-snap pour une navigation fluide entre les éléments.

CSSHorizontalSnap

Rotate In

Cartes apparaissant avec rotation et scale via view() et animation-delay.

CSSRotateStagger

Blur Reveal

Effet de mise au point progressive avec blur(20px) animé vers blur(0) via view().

CSSBlurReveal

Counter Scroll

Compteurs animés qui s'incrémentent lorsqu'ils entrent dans la vue du conteneur.

JSCounterScroll

Scroll-Driven Fade

Animation CSS native pilotée par le scroll avec animation-timeline: view() et entry range.

CSSViewFade

View Timeline Scale

Éléments qui s'agrandissent progressivement via animation-timeline: view() et cover range.

CSSScaleView

Scroll Progress Bar

Barre de progression sticky liée au scroll du conteneur via scroll(nearest).

CSSProgressSticky

Parallax Layers CSS

Couches se déplaçant a vitesses différentes via scroll(nearest) pour un effet de profondeur.

CSSParallaxLayers

Rotate On Scroll

Élément effectuant une rotation de 720 degrés liée au scroll via scroll(nearest).

CSSRotateScroll

Slide In CSS Native

Slide gauche/droite natif CSS avec animation-timeline: view() et cover range.

CSSSlideNative

Blur to Clear

Transition de blur(10px) a blur(0) pour un effet cinématographique via view().

CSSBlurView

Stagger Reveal CSS

Grille d'items avec animation-delay incremental CSS natif et view() pour un effet cascade.

CSSStaggerNative

Clip Path Reveal

Révélation progressive via clip-path: inset() animé par view() et cover range.

CSSClip-pathReveal

Color Change

Changement de couleur progressif (violet, rose, cyan, vert) lié au scroll via scroll(nearest).

CSSColorScroll

Barre de progression

Scrollez pour voir la barre se remplir. Utilise animation-timeline: scroll() pour lier l'animation au défilement du conteneur.

Scrollez ↓

Progress Bar

Barre de progression liée au scroll via animation-timeline: scroll(). Se remplit de 0% à 100% en CSS pur.

CSS Scroll Progress
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="sdc-scroll-container">
    <div class="sdc-progress-bar">
      <div class="sdc-progress-fill"></div>
    </div>
    <div class="sdc-progress-content">
      <h3>Barre de progression</h3>
      <p>Scrollez pour voir la barre se remplir. Utilise animation-timeline: scroll() pour lier l'animation au défilement du conteneur.</p>
      <div class="sdc-progress-block"></div>
      <div class="sdc-progress-block"></div>
      <div class="sdc-progress-block"></div>
      <div class="sdc-progress-block"></div>
    </div>
  </div>
  <span class="sdc-scroll-hint">Scrollez ↓</span>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.sdc-scroll-container {
  width: 100%;
  height: 280px;
  overflow-y: auto;
  position: relative;
  scroll-behavior: smooth;
}

.sdc-scroll-container::-webkit-scrollbar {
  width: 4px;
}

.sdc-scroll-container::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.05);
}

.sdc-scroll-container::-webkit-scrollbar-thumb {
  background: rgba(139, 92, 246, 0.4);
  border-radius: 2px;
}

.sdc-scroll-hint {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.3);
  z-index: 5;
  pointer-events: none;
  animation: sdcHintPulse 2s ease-in-out infinite;
}

.sdc-progress-bar {
  position: sticky;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: rgba(255, 255, 255, 0.1);
  z-index: 10;
}

.sdc-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #8b5cf6, #ec4899);
  transform-origin: left;
  animation: sdcProgressGrow linear;
  animation-timeline: scroll(nearest);
  transform: scaleX(0);
}

.sdc-progress-content {
  padding: 20px;
  height: 800px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.sdc-progress-content h3 {
  font-size: 1rem;
  font-weight: 700;
  color: #fff;
  margin: 0;
}

.sdc-progress-content p {
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.5);
  margin: 0;
  line-height: 1.6;
}

.sdc-progress-block {
  height: 120px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

@keyframes sdcHintPulse {

  0%,
  100% {
    opacity: 0.3;
  }

  50% {
    opacity: 0.7;
  }
}

@keyframes sdcProgressGrow {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}
JavaScript
/* CSS pur — aucun JavaScript requis */

Fade In Reveal

Éléments qui apparaissent progressivement via animation-timeline: view() et animation-range: entry.

CSS View Reveal

Parallax Layers

Couches parallaxes avec des vitesses différentes, pilotées uniquement par scroll() en CSS natif.

CSS Parallax Layers

Scale on Scroll

Cartes qui grandissent de 70% à 100% en entrant dans la vue via animation-timeline: view().

CSS Scale View

Color Shift

Gradient de fond qui évolue à travers 5 palettes de couleurs en scrollant, via animation-timeline: scroll().

CSS Gradient Scroll

Text Reveal

Mots qui glissent depuis le bas et se révèlent progressivement au défilement avec view().

CSS Text Reveal

Rotate on Scroll

Forme géométrique avec rotation à 720° liée au scroll. Les bordures tournent en sens inverse.

CSS Rotate Scroll

Slide In Cards

Cartes qui glissent alternativement depuis la gauche et la droite avec view() et animation-range: entry.

CSS Slide View

Zoom & Blur

Cercle qui zoome et se défloute au centre du scroll, puis continue à zoomer et se refloute en sortant.

CSS Zoom Blur

Horizontal Scroll

Scroll vertical converti en défilement horizontal des cartes via animation-timeline: scroll().

CSS Horizontal Scroll

Chapitre 1 : Introduction

Bienvenue dans cette démonstration de barre de progression liée au scroll. La barre en haut de ce conteneur progresse en fonction de votre position de défilement.

Cet effet utilise la propriété CSS animation-timeline: scroll() qui lie une animation @keyframes directement à la position de défilement du conteneur.

Chapitre 2 : Fonctionnement

La propriété scroll-timeline crée un timeline nommé sur le conteneur scrollable. L'animation progress-bar utilise ensuite ce timeline pour animer la propriété transform: scaleX().

Le résultat est une barre de progression fluide qui représente exactement le pourcentage de contenu lu, sans aucun JavaScript.

Chapitre 3 : Applications

Idéal pour les articles de blog, les pages de documentation, les tutoriels ou tout contenu long où l'utilisateur souhaite visualiser sa progression de lecture.

Compatible avec les navigateurs modernes supportant les Scroll-Driven Animations (Chrome 115+, Edge 115+).

Chapitre 4 : Conclusion

Les animations liées au scroll ouvrent de nouvelles possibilités pour l'expérience utilisateur, le tout en CSS pur sans impact sur les performances JavaScript.

Scrollez pour voir l'effet

Progress Bar

Barre de progression de lecture pilotée par animation-timeline: scroll(), zéro JavaScript.

CSS scroll() Progress
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="progress-scroll-container">
    <div class="slr-progress-bar-track">
      <div class="slr-progress-bar-fill"></div>
    </div>
    <div class="progress-content">
      <h3>Chapitre 1 : Introduction</h3>
      <p>Bienvenue dans cette démonstration de barre de progression liée au scroll. La barre en haut de ce conteneur progresse en fonction de votre position de défilement.</p>
      <p>Cet effet utilise la propriété CSS animation-timeline: scroll() qui lie une animation @keyframes directement à la position de défilement du conteneur.</p>
      <h3>Chapitre 2 : Fonctionnement</h3>
      <p>La propriété scroll-timeline crée un timeline nommé sur le conteneur scrollable. L'animation progress-bar utilise ensuite ce timeline pour animer la propriété transform: scaleX().</p>
      <p>Le résultat est une barre de progression fluide qui représente exactement le pourcentage de contenu lu, sans aucun JavaScript.</p>
      <h3>Chapitre 3 : Applications</h3>
      <p>Idéal pour les articles de blog, les pages de documentation, les tutoriels ou tout contenu long où l'utilisateur souhaite visualiser sa progression de lecture.</p>
      <p>Compatible avec les navigateurs modernes supportant les Scroll-Driven Animations (Chrome 115+, Edge 115+).</p>
      <h3>Chapitre 4 : Conclusion</h3>
      <p>Les animations liées au scroll ouvrent de nouvelles possibilités pour l'expérience utilisateur, le tout en CSS pur sans impact sur les performances JavaScript.</p>
    </div>
  </div>
  <span class="slr-scroll-hint">Scrollez pour voir l'effet</span>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.slr-scroll-hint {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.4);
  pointer-events: none;
  z-index: 10;
  animation: hintBounce 2s ease-in-out infinite;
}

.progress-scroll-container {
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  scroll-timeline: --progressScroll y;
}

.slr-progress-bar-track {
  position: sticky;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: rgba(255, 255, 255, 0.1);
  z-index: 5;
}

.slr-progress-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #6366f1, #d946ef, #f59e0b);
  transform-origin: left;
  transform: scaleX(0);
  animation: progressGrow linear both;
  animation-timeline: --progressScroll;
}

.progress-content {
  padding: 16px 12px;
}

.progress-content p {
  font-size: 0.8rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: 12px;
}

.progress-content h3 {
  font-size: 0.9rem;
  color: #a78bfa;
  margin-bottom: 8px;
}

@keyframes hintBounce {

  0%,
  100% {
    transform: translateX(-50%) translateY(0);
  }

  50% {
    transform: translateX(-50%) translateY(-4px);
  }
}

@keyframes progressGrow {
  from {
    transform: scaleX(0);
  }

  to {
    transform: scaleX(1);
  }
}
JavaScript
/* CSS pur — aucun JavaScript requis */

Horizontal Scroll Section

Section défilant horizontalement lors du scroll vertical, pur CSS avec scroll-timeline.

CSS scroll-timeline Horizontal

Sticky Reveal Stack

Cartes s'empilant et se révélant une par une au scroll avec view() timeline.

CSS view() Stack

Text Line Reveal

Chaque mot se colore progressivement lors du scroll via animation-range et view().

CSS animation-range Text

Zoom Into Content

Contenu démarrant dézoomé qui s'agrandit à 100% au scroll, effet d'ouverture cinématique.

CSS view() Zoom

Rotation on Scroll

Élément tournant proportionnellement à la position de scroll, effet cadran/boussole.

CSS scroll() Rotation

Path Drawing on Scroll

Tracé SVG se dessinant via stroke-dashoffset animé par le scroll, pur CSS.

CSS SVG scroll()

Parallax Layers

Parallaxe multi-couches entièrement contrôlé par scroll() timeline, sans JS.

CSS scroll() Parallax

Introduction

Le scrollytelling est une technique narrative qui utilise le defilement de la page pour guider l'utilisateur a travers une histoire visuelle immersive.

Chapitre 1

Les animations declenchees par le scroll permettent de reveler progressivement le contenu, creant un rythme naturel de lecture qui captive l'attention.

Chapitre 2

En combinant parallaxe, transitions et effets visuels, chaque section devient une scene dans un recit plus large, transformant un simple site web en experience narrative.

Chapitre 3

Les meilleurs exemples de scrollytelling equilibrent esthetique et fonctionnalite, guidant l'utilisateur sans le submerger d'effets excessifs.

Conclusion

Maitrisez ces techniques pour creer des experiences web memorables qui racontent votre histoire avec elegance et fluidite.

Scrollez pour explorer

Progress Bar

Barre de progression horizontale qui se remplit proportionnellement au défilement du contenu.

CSS JavaScript UX
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="st-progress-scroll">
    <div class="scroll-container" id="progress-scroll">
      <div class="st-progress-bar-track">
        <div class="st-progress-bar-fill" id="progress-fill"></div>
      </div>
      <div class="progress-inner">
        <h3>Introduction</h3>
        <p>Le scrollytelling est une technique narrative qui utilise le defilement de la page pour guider l'utilisateur a travers une histoire visuelle immersive.</p>
        <div class="section-divider"></div>
        <h3>Chapitre 1</h3>
        <p>Les animations declenchees par le scroll permettent de reveler progressivement le contenu, creant un rythme naturel de lecture qui captive l'attention.</p>
        <div class="section-divider"></div>
        <h3>Chapitre 2</h3>
        <p>En combinant parallaxe, transitions et effets visuels, chaque section devient une scene dans un recit plus large, transformant un simple site web en experience narrative.</p>
        <div class="section-divider"></div>
        <h3>Chapitre 3</h3>
        <p>Les meilleurs exemples de scrollytelling equilibrent esthetique et fonctionnalite, guidant l'utilisateur sans le submerger d'effets excessifs.</p>
        <div class="section-divider"></div>
        <h3>Conclusion</h3>
        <p>Maitrisez ces techniques pour creer des experiences web memorables qui racontent votre histoire avec elegance et fluidite.</p>
      </div>
    </div>
    <span class="scroll-hint-label">Scrollez pour explorer</span>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.st-progress-scroll {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-height: 100%;
  background: #0a0a0f;
  color: #fff;
  font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

.scroll-container {
  width: 100%;
  height: 280px;
  overflow: hidden auto;
  position: relative;
  scroll-behavior: smooth;
}

.scroll-container::-webkit-scrollbar {
  width: 4px;
}

.scroll-container::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.03);
}

.scroll-container::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.15);
  border-radius: 4px;
}

.scroll-container::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.3);
}

.scroll-hint-label {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.3);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  pointer-events: none;
  z-index: 10;
  animation: pulseHint 2s ease-in-out infinite;
}

.st-progress-bar-track {
  position: sticky;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: rgba(255, 255, 255, 0.08);
  z-index: 20;
}

.st-progress-bar-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #6366f1, #a855f7, #ec4899);
  border-radius: 0 2px 2px 0;
  transition: width 0.05s linear;
}

.progress-inner {
  padding: 24px 20px;
}

.progress-inner h3 {
  font-size: 1rem;
  font-weight: 700;
  color: #fff;
  margin: 0 0 12px;
}

.progress-inner p {
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.5);
  line-height: 1.7;
  margin: 0 0 16px;
}

.progress-inner .section-divider {
  width: 60px;
  height: 2px;
  background: linear-gradient(90deg, #6366f1, transparent);
  margin: 20px 0;
}

@keyframes pulseHint {

  0%,
  100% {
    opacity: 0.3;
  }

  50% {
    opacity: 0.7;
  }
}
JavaScript
(function() {
  /* fx-0575 — Introduction (Progress Bar) */
  (function() {
    const progressScroll = document.getElementById('progress-scroll');
    const progressFill = document.getElementById('progress-fill');

    if (progressScroll && progressFill) {
      progressScroll.addEventListener('scroll', () => {
        const scrollTop = progressScroll.scrollTop;
        const scrollHeight = progressScroll.scrollHeight - progressScroll.clientHeight;
        const progress = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0;
        progressFill.style.width = progress + '%';
      });
    }
  })();
})();

Parallax Layers

Trois couches visuelles se déplacent à des vitesses différentes pour créer un effet de profondeur immersif.

CSS JavaScript Parallaxe

Reveal on Scroll

Les éléments apparaissent avec un fondu et un glissement vertical lorsqu'ils entrent dans la zone visible.

IntersectionObserver CSS Animation

Sticky Horizontal

Défilement horizontal automatique simulant une navigation par panneaux, idéal pour présenter des étapes ou des projets.

CSS Animation Auto-play

Text Highlight on Scroll

Chaque mot s'illumine progressivement au fur et a mesure du défilement, créant un effet de lecture guidée.

JavaScript CSS Typographie

Zoom on Scroll

Un élément grossit progressivement avec le défilement, passant d'un petit objet à une vue plein écran.

JavaScript CSS Transform Scroll

Number Counter Scroll

Les compteurs s'animent de zéro à leur valeur cible proportionnellement à la position de défilement.

JavaScript Animation Data

Timeline Scroll

Chronologie verticale interactive avec une ligne qui se dessine progressivement et des éléments qui apparaissent au défilement.

JavaScript CSS Timeline

Image Sequence

Simulation d'animation image par image pilotée par le scroll, similaire aux pages produit Apple.

JavaScript CSS Sequence

Scroll Snap Sections

Sections pleine hauteur avec accrochage magnétique et indicateur de pagination latéral.

CSS Scroll Snap JavaScript Navigation

Sticky Scroll

8 effets de scroll sticky et parallax avances.

01

Premiere Section

L'image reste fixe pendant que le contenu defile. Technique ideale pour presenter des fonctionnalites.

Deuxieme Section

Chaque section de texte declenche un changement visuel dans l'image sticky.

Troisieme Section

Les transitions douces guident l'utilisateur a travers le contenu de maniere fluide.

Quatrieme Section

Pattern utilise dans le journalisme interactif et les sites de produits.

Scrollez ↓

Sticky Image Change

Image sticky qui change pendant que le contenu défile avec des panneaux révélés via view().

CSSStickyScroll
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="sdc-scroll-container">
    <div class="ss-imgchange-content">
      <div class="ss-imgchange-display">01</div>
      <div class="ss-imgchange-panels">
        <div class="ss-imgchange-panel"><h4>Premiere Section</h4><p>L'image reste fixe pendant que le contenu defile. Technique ideale pour presenter des fonctionnalites.</p></div>
        <div class="ss-imgchange-panel"><h4>Deuxieme Section</h4><p>Chaque section de texte declenche un changement visuel dans l'image sticky.</p></div>
        <div class="ss-imgchange-panel"><h4>Troisieme Section</h4><p>Les transitions douces guident l'utilisateur a travers le contenu de maniere fluide.</p></div>
        <div class="ss-imgchange-panel"><h4>Quatrieme Section</h4><p>Pattern utilise dans le journalisme interactif et les sites de produits.</p></div>
      </div>
    </div>
  </div>
  <span class="sdc-scroll-hint">Scrollez ↓</span>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.ss-imgchange-content {
  height: 1200px;
  padding: 20px 12px;
}

.ss-imgchange-display {
  width: 100%;
  height: 120px;
  border-radius: 14px;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  font-weight: 800;
  color: white;
  position: sticky;
  top: 10px;
  z-index: 2;
  animation: ssImgChange linear;
  animation-timeline: scroll(nearest);
}

.ss-imgchange-panels {
  padding-top: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.ss-imgchange-panel {
  padding: 16px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  opacity: 0;
  transform: translateY(20px);
  animation: sbFadeUp linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 50%;
}

.ss-imgchange-panel h4 {
  font-size: 0.85rem;
  font-weight: 700;
  color: #fff;
  margin: 0 0 6px;
}

.ss-imgchange-panel p {
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.5);
  margin: 0;
  line-height: 1.5;
}

.sdc-scroll-container {
  width: 100%;
  height: 280px;
  overflow-y: auto;
  position: relative;
  scroll-behavior: smooth;
}

.sdc-scroll-container::-webkit-scrollbar {
  width: 4px;
}

.sdc-scroll-container::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.05);
}

.sdc-scroll-container::-webkit-scrollbar-thumb {
  background: rgba(139, 92, 246, 0.4);
  border-radius: 2px;
}

.sdc-scroll-hint {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.3);
  z-index: 5;
  pointer-events: none;
  animation: sdcHintPulse 2s ease-in-out infinite;
}

@keyframes sbFadeUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes ssImgChange {

  0%,
  20% {
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    box-shadow: 0 8px 30px rgba(99, 102, 241, 0.3);
  }

  25%,
  45% {
    background: linear-gradient(135deg, #8b5cf6, #d946ef);
    box-shadow: 0 8px 30px rgba(139, 92, 246, 0.3);
  }

  50%,
  70% {
    background: linear-gradient(135deg, #d946ef, #f43f5e);
    box-shadow: 0 8px 30px rgba(217, 70, 239, 0.3);
  }

  75%,
  100% {
    background: linear-gradient(135deg, #f43f5e, #f59e0b);
    box-shadow: 0 8px 30px rgba(244, 63, 94, 0.3);
  }
}

@keyframes sdcHintPulse {

  0%,
  100% {
    opacity: 0.3;
  }

  50% {
    opacity: 0.7;
  }
}
JavaScript
/* CSS pur — aucun JavaScript requis */

Horizontal Scroll

Section a défilement horizontal avec snap pour naviguer entre les étapes du workflow.

CSSHorizontalSticky

Card Stack

Cartes qui s'empilent avec position sticky et animation view() dans le conteneur.

CSSStackSticky

Progress Reveal

Barre de progression sticky avec items révélés progressivement via scroll(nearest) et view().

CSSProgressReveal

Split Screen Sticky

Visuel sticky avec SVG rotatif et contenu révélé par scroll via view() et scroll(nearest).

CSSSplitSticky

Zoom In Sticky

Élément qui zoome progressivement de scale(1) à scale(2.2) via scroll(nearest).

CSSZoomScroll

Text Highlight Scroll

Mots colorés séquentiellement au scroll avec JS scope au conteneur.

JSTextHighlight

Layered Parallax

5 couches se déplaçant a vitesses différentes via scroll(nearest) pour un effet parallax complet.

CSSParallaxLayers

Scroll Snap

6 effets de scroll snap pour une navigation précise.

Section 1

Faites défiler pour passer à la suivante

Section 2

Le scroll s'arrête automatiquement

Section 3

Expérience fluide et contrôlée

Section 4

Dernière section

Scrollez ↓

Vertical Snap

Sections s'ancrant automatiquement au début via scroll-snap-type: y mandatory.

CSSSnapVertical
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="sn-vsnap-wrap">
    <div class="sn-vsnap-container">
      <div class="sn-vsnap-section"><h4>Section 1</h4><p>Faites défiler pour passer à la suivante</p></div>
      <div class="sn-vsnap-section"><h4>Section 2</h4><p>Le scroll s'arrête automatiquement</p></div>
      <div class="sn-vsnap-section"><h4>Section 3</h4><p>Expérience fluide et contrôlée</p></div>
      <div class="sn-vsnap-section"><h4>Section 4</h4><p>Dernière section</p></div>
    </div>
    <span class="sdc-scroll-hint">Scrollez ↓</span>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.sn-vsnap-wrap {
  position: relative;
  width: 100%;
  background: #1e1b4b;
  color: #fff;
  font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

.sn-vsnap-container {
  width: 100%;
  height: 280px;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  scroll-behavior: smooth;
}

.sn-vsnap-section {
  box-sizing: border-box;
  height: 280px;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px;
  text-align: center;
}

.sn-vsnap-section:nth-child(1) {
  background: linear-gradient(135deg, #1e1b4b, #312e81);
}

.sn-vsnap-section:nth-child(2) {
  background: linear-gradient(135deg, #312e81, #4c1d95);
}

.sn-vsnap-section:nth-child(3) {
  background: linear-gradient(135deg, #4c1d95, #6d28d9);
}

.sn-vsnap-section:nth-child(4) {
  background: linear-gradient(135deg, #6d28d9, #7c3aed);
}

.sn-vsnap-section h4 {
  font-size: 0.9rem;
  font-weight: 700;
  color: white;
  margin: 0;
}

.sn-vsnap-section p {
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.6);
  margin: 0;
}

.sdc-scroll-hint {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.3);
  z-index: 5;
  pointer-events: none;
  animation: sdcHintPulse 2s ease-in-out infinite;
}

@keyframes sdcHintPulse {

  0%,
  100% {
    opacity: 0.3;
  }

  50% {
    opacity: 0.7;
  }
}
JavaScript
/* CSS pur — aucun JavaScript requis */

Horizontal Snap

Défilement horizontal avec ancrage automatique via scroll-snap-type: x mandatory.

CSSSnapHorizontal

Mixed Content Snap

Sections de tailles différentes avec scroll-snap-type: y proximity pour flexibilité.

CSSMixedSnap

Snap + Progress

Snap vertical avec barre de progression et dots indicateurs via JS scope au conteneur.

JSSnapProgress

Smooth Snap

Snap avec animations déclenchées par IntersectionObserver scope au conteneur.

JSSnapSmooth

Chapitre 1 — Le principe

Scrollez à l'intérieur de cette zone : la barre lumineuse à gauche se remplit au rythme exact de votre lecture, avec un halo qui réagit à la position. Plus vous avancez, plus le faisceau monte.

Chapitre 2 — Le repère

Le curseur lumineux glisse le long de l'axe vertical. C'est un repère de progression élégant et discret, parfait pour un article long, une page de documentation ou un récit qui se déroule au scroll.

Chapitre 3 — La mécanique

Aucune dépendance externe : un simple écouteur de scroll calcule le ratio défilé / hauteur totale et met à jour une variable CSS. Léger, fluide, et entièrement accessible.

Chapitre 4 — La performance

L'écouteur est passif et ne touche qu'à une custom property, donc zéro reflow coûteux. Le rendu reste à 60 fps même sur mobile, et la barre suit le doigt au pixel près.

Chapitre 5 — L'accessibilité

La barre est purement décorative (aria-hidden) : le contenu reste pleinement lisible et navigable au clavier. En mode « mouvement réduit », le défilement instantané remplace le smooth-scroll.

Chapitre 6 — La fin

Arrivé tout en bas, la barre est pleine à 100% et le pourcentage l'indique. Un repère clair, du début à la fin, sans jamais voler l'attention au contenu.

Scroll Progress Beam

Une barre lumineuse latérale qui se remplit avec la progression du scroll, halo réactif et curseur glissant. Repère de lecture premium et discret.

💡 Idéal pour : barre de progression d'article, page longue / docs, onboarding multi-sections, landing storytelling.

Scroll CSS Variables Vanilla JS Gratuit
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="spb-scene">
    <div class="spb-beam" aria-hidden="true"><div class="spb-beam-fill"></div><div class="spb-beam-dot"></div></div>
    <div class="spb-pct" aria-hidden="true">0%</div>
    <div class="spb-scroll">
      <div class="spb-block">
        <h4>Chapitre 1 — Le principe</h4>
        <p>Scrollez à l'intérieur de cette zone : la barre lumineuse à gauche se remplit au rythme exact de votre lecture, avec un halo qui réagit à la position. Plus vous avancez, plus le faisceau monte.</p>
        <h4>Chapitre 2 — Le repère</h4>
        <p>Le curseur lumineux glisse le long de l'axe vertical. C'est un repère de progression élégant et discret, parfait pour un article long, une page de documentation ou un récit qui se déroule au scroll.</p>
        <h4>Chapitre 3 — La mécanique</h4>
        <p>Aucune dépendance externe : un simple écouteur de scroll calcule le ratio défilé / hauteur totale et met à jour une variable CSS. Léger, fluide, et entièrement accessible.</p>
        <h4>Chapitre 4 — La performance</h4>
        <p>L'écouteur est passif et ne touche qu'à une custom property, donc zéro reflow coûteux. Le rendu reste à 60 fps même sur mobile, et la barre suit le doigt au pixel près.</p>
        <h4>Chapitre 5 — L'accessibilité</h4>
        <p>La barre est purement décorative (aria-hidden) : le contenu reste pleinement lisible et navigable au clavier. En mode « mouvement réduit », le défilement instantané remplace le smooth-scroll.</p>
        <h4>Chapitre 6 — La fin</h4>
        <p>Arrivé tout en bas, la barre est pleine à 100% et le pourcentage l'indique. Un repère clair, du début à la fin, sans jamais voler l'attention au contenu.</p>
      </div>
    </div>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.spb-scene {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  max-height: 340px;
  border-radius: 14px;
  overflow: hidden;
  isolation: isolate;
  background: #0c1022;
  font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

.spb-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  scroll-behavior: smooth;
  padding: 22px 22px 22px 40px;
  box-sizing: border-box;
}

.spb-scroll::-webkit-scrollbar {
  width: 0;
}

.spb-scroll {
  scrollbar-width: none;
}

@media (prefers-reduced-motion: reduce) {
  .spb-scroll {
    scroll-behavior: auto;
  }
}

.spb-block {
  color: #e7e9f5;
}

.spb-block h4 {
  margin: 0 0 8px;
  font-size: 16px;
}

.spb-block p {
  margin: 0 0 22px;
  font-size: 13px;
  line-height: 1.7;
  color: #aeb2c8;
}

.spb-beam {
  position: absolute;
  left: 14px;
  top: 18px;
  bottom: 18px;
  width: 4px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.10);
  z-index: 3;
  pointer-events: none;
}

.spb-beam-fill {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(var(--spb-p, 0) * 100%);
  border-radius: 4px;
  background: linear-gradient(180deg, #5cffd8, #6d8bff);
  box-shadow: 0 0 12px rgba(109, 139, 255, 0.8), 0 0 4px rgba(92, 255, 216, 0.9);
}

.spb-beam-dot {
  position: absolute;
  left: 50%;
  top: calc(var(--spb-p, 0) * 100%);
  width: 12px;
  height: 12px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  box-shadow: 0 0 14px 3px rgba(109, 139, 255, 0.9);
}

.spb-pct {
  position: absolute;
  right: 14px;
  top: 12px;
  z-index: 3;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: #aeb2c8;
  background: rgba(0, 0, 0, 0.4);
  padding: 3px 9px;
  border-radius: 999px;
  pointer-events: none;
}
JavaScript
(function() {
  /* fx-0793 — Scroll Progress Beam (IIFE scopée) */
  (function() {
    document.querySelectorAll('.spb-scene').forEach(function(scene) {
      var scroller = scene.querySelector('.spb-scroll');
      var beam = scene.querySelector('.spb-beam');
      var pct = scene.querySelector('.spb-pct');
      if (!scroller || !beam) return;

      function update() {
        var max = scroller.scrollHeight - scroller.clientHeight;
        var p = max > 0 ? scroller.scrollTop / max : 0;
        beam.style.setProperty('--spb-p', p.toFixed(4));
        if (pct) pct.textContent = Math.round(p * 100) + '%';
      }
      scroller.addEventListener('scroll', update, {
        passive: true
      });
      window.addEventListener('resize', update);
      update();
    });
  })();
})();
Scrollez ici ↓

SVG Blinds Mask

Des persiennes s'ouvrent lamelle par lamelle au rythme exact de votre défilement et révèlent la scène. Chaque lamelle est déphasée par son index — mapping direct scroll → CSS, aucune animation subie.

💡 Idéal pour : révéler un hero visuel, une image produit, une section portfolio au scroll.

Scroll Mask Reveal
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="sbm-scene">
      <div class="sbm-scroll" id="sbmScroll" tabindex="0" role="region" aria-label="Zone de démonstration au défilement">
        <div class="sbm-track" style="height:340%"></div>
      </div>
      <div class="sbm-stage" aria-hidden="true">
        <div class="sbm-photo">
          <div class="sbm-caption">RÉVÉLÉ</div>
        </div>
        <div class="sbm-slats">
        <span class="sbm-slat" style="--k:0"></span>
        <span class="sbm-slat" style="--k:1"></span>
        <span class="sbm-slat" style="--k:2"></span>
        <span class="sbm-slat" style="--k:3"></span>
        <span class="sbm-slat" style="--k:4"></span>
        <span class="sbm-slat" style="--k:5"></span>
        <span class="sbm-slat" style="--k:6"></span>
        <span class="sbm-slat" style="--k:7"></span>
        </div>
      </div>
      <span class="sbm-hint">Scrollez ici ↓</span>
    </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.sbm-scene {
  position: relative;
  width: 100%;
  max-width: 430px;
  height: 260px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .08);
  background: #0d0d16;
  --p: 0
}

.sbm-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  z-index: 3;
  scrollbar-width: thin
}

.sbm-stage {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none
}

.sbm-hint {
  position: absolute;
  right: 10px;
  bottom: 8px;
  z-index: 2;
  font-size: .6rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #8f8fb0;
  opacity: calc(1 - var(--p) * 3);
  pointer-events: none
}

.sbm-scroll:focus-visible {
  outline: 2px solid #a78bfa;
  outline-offset: -2px
}

.sbm-track {
  width: 100%
}

.sbm-photo {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: radial-gradient(circle at 30% 25%, rgba(34, 255, 170, .25), transparent 55%), linear-gradient(160deg, #143a5e, #7c3aed 70%, #db2777)
}

.sbm-caption {
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: .3em;
  color: #fff;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .6);
  opacity: clamp(0, (var(--p) - .75) * 4, 1)
}

.sbm-slats {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column
}

.sbm-slat {
  flex: 1;
  background: #0d0d16;
  transform: scaleY(clamp(0, 1 - (var(--p) * 9 - var(--k)), 1));
  transform-origin: 50% 50%
}
JavaScript
(function() {
  (function() {
    /* fx-0778 — SVG Blinds Mask : progression de scroll → variable CSS --p (rAF, passif) */
    var sc = document.getElementById('sbmScroll');
    if (!sc) return;
    var host = sc.closest('.sbm-scene');
    var raf = null;

    function update() {
      raf = null;
      var max = sc.scrollHeight - sc.clientHeight;
      var p = max > 0 ? sc.scrollTop / max : 0;
      host.style.setProperty('--p', p.toFixed(4));
    }
    sc.addEventListener('scroll', function() {
      if (!raf) raf = requestAnimationFrame(update);
    }, {
      passive: true
    });
    update();
  })();
})();
Scrollez ici ↓

Corner Morph Overlay

Un cercle naît dans le coin et engloutit l'écran au fil du défilement pour révéler la section suivante — transition de chapitre pilotée au scroll, clip-path pur.

💡 Idéal pour : transitions de sections, storytelling chapitré, landing pages narratives.

Scroll clip-path Transition
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="cmo-scene">
      <div class="cmo-scroll" id="cmoScroll" tabindex="0" role="region" aria-label="Zone de démonstration au défilement">
        <div class="cmo-track" style="height:340%"></div>
      </div>
      <div class="cmo-stage" aria-hidden="true">
        <div class="cmo-a"><h4>Chapitre I</h4><p>Continuez à défiler…</p></div>
        <div class="cmo-b"><h4>Chapitre II</h4><p>…le coin a tout englouti.</p></div>
      </div>
      <span class="cmo-hint">Scrollez ici ↓</span>
    </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.cmo-scene {
  position: relative;
  width: 100%;
  max-width: 430px;
  height: 260px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .08);
  background: #0d0d16;
  --p: 0
}

.cmo-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  z-index: 3;
  scrollbar-width: thin
}

.cmo-stage {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none
}

.cmo-hint {
  position: absolute;
  right: 10px;
  bottom: 8px;
  z-index: 2;
  font-size: .6rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #8f8fb0;
  opacity: calc(1 - var(--p) * 3);
  pointer-events: none
}

.cmo-scroll:focus-visible {
  outline: 2px solid #a78bfa;
  outline-offset: -2px
}

.cmo-track {
  width: 100%
}

.cmo-a,
.cmo-b {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
  gap: 4px
}

.cmo-a {
  background: linear-gradient(160deg, #16162a, #101020);
  color: #cfcfe8
}

.cmo-b {
  background: radial-gradient(circle at 88% 88%, rgba(255, 209, 102, .25), transparent 50%), linear-gradient(200deg, #2b1440, #7c3aed);
  color: #fff;
  clip-path: circle(calc(6% + var(--p) * 140%) at 90% 88%)
}

.cmo-a h4,
.cmo-b h4 {
  margin: 0;
  font-size: 1.05rem;
  letter-spacing: .18em;
  text-transform: uppercase
}

.cmo-a p,
.cmo-b p {
  margin: 0;
  font-size: .72rem;
  opacity: .75
}
JavaScript
(function() {
  (function() {
    /* fx-0779 — Corner Morph Overlay : progression de scroll → variable CSS --p (rAF, passif) */
    var sc = document.getElementById('cmoScroll');
    if (!sc) return;
    var host = sc.closest('.cmo-scene');
    var raf = null;

    function update() {
      raf = null;
      var max = sc.scrollHeight - sc.clientHeight;
      var p = max > 0 ? sc.scrollTop / max : 0;
      host.style.setProperty('--p', p.toFixed(4));
    }
    sc.addEventListener('scroll', function() {
      if (!raf) raf = requestAnimationFrame(update);
    }, {
      passive: true
    });
    update();
  })();
})();
Scrollez ici ↓

Corner Morph Cards

Trois cartes éparpillées aux coins organiques se redressent, s'alignent et adoucissent leurs angles au fil du défilement — l'assemblage se joue entièrement en border-radius et transform.

💡 Idéal pour : entrées de grilles produits, portfolios, sections « nos services ».

Scroll border-radius Cards
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="cmc-scene">
      <div class="cmc-scroll" id="cmcScroll" tabindex="0" role="region" aria-label="Zone de démonstration au défilement">
        <div class="cmc-track" style="height:340%"></div>
      </div>
      <div class="cmc-stage" aria-hidden="true">
        <div class="cmc-row">
          <div class="cmc-card" style="--r:-9deg; --g:linear-gradient(145deg,#22ffaa,#0e7490)">01</div>
          <div class="cmc-card" style="--r:5deg;  --g:linear-gradient(145deg,#7c3aed,#db2777)">02</div>
          <div class="cmc-card" style="--r:11deg; --g:linear-gradient(145deg,#ffd166,#f4a300)">03</div>
        </div>
      </div>
      <span class="cmc-hint">Scrollez ici ↓</span>
    </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.cmc-scene {
  position: relative;
  width: 100%;
  max-width: 430px;
  height: 260px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .08);
  background: #0d0d16;
  --p: 0
}

.cmc-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  z-index: 3;
  scrollbar-width: thin
}

.cmc-stage {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none
}

.cmc-hint {
  position: absolute;
  right: 10px;
  bottom: 8px;
  z-index: 2;
  font-size: .6rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #8f8fb0;
  opacity: calc(1 - var(--p) * 3);
  pointer-events: none
}

.cmc-scroll:focus-visible {
  outline: 2px solid #a78bfa;
  outline-offset: -2px
}

.cmc-track {
  width: 100%
}

.cmc-row {
  position: absolute;
  inset: 0;
  display: flex;
  gap: calc(34px - var(--p) * 22px);
  align-items: center;
  justify-content: center
}

.cmc-card {
  width: 86px;
  height: 116px;
  display: grid;
  place-items: center;
  background: var(--g);
  color: rgba(255, 255, 255, .9);
  font-weight: 800;
  font-size: 1.1rem;
  border-radius: calc(50px - var(--p) * 40px) calc(14px + var(--p) * 0px) calc(46px - var(--p) * 36px) calc(18px - var(--p) * 8px);
  transform: rotate(calc(var(--r) * (1 - var(--p)))) translateY(calc((1 - var(--p)) * 12px));
  box-shadow: 0 10px 24px rgba(0, 0, 0, .45)
}
JavaScript
(function() {
  (function() {
    /* fx-0780 — Corner Morph Cards : progression de scroll → variable CSS --p (rAF, passif) */
    var sc = document.getElementById('cmcScroll');
    if (!sc) return;
    var host = sc.closest('.cmc-scene');
    var raf = null;

    function update() {
      raf = null;
      var max = sc.scrollHeight - sc.clientHeight;
      var p = max > 0 ? sc.scrollTop / max : 0;
      host.style.setProperty('--p', p.toFixed(4));
    }
    sc.addEventListener('scroll', function() {
      if (!raf) raf = requestAnimationFrame(update);
    }, {
      passive: true
    });
    update();
  })();
})();
Scrollez ici ↓

Concentric Rings Morph

Cinq anneaux concentriques se tracent, tournent et glissent en teinte (OKLCH par index) au rythme exact du défilement, autour d'un pourcentage de progression.

💡 Idéal pour : progression de lecture, étapes d'onboarding, compteurs de scroll immersifs.

Scroll SVG OKLCH
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <div class="crm-scene">
      <div class="crm-scroll" id="crmScroll" tabindex="0" role="region" aria-label="Zone de démonstration au défilement">
        <div class="crm-track" style="height:340%"></div>
      </div>
      <div class="crm-stage" aria-hidden="true">
        <svg class="crm-svg" viewBox="0 0 120 120" aria-hidden="true">
          <circle class="crm-ring" style="--i:0" cx="60" cy="60" r="14"/>
          <circle class="crm-ring" style="--i:1" cx="60" cy="60" r="25"/>
          <circle class="crm-ring" style="--i:2" cx="60" cy="60" r="36"/>
          <circle class="crm-ring" style="--i:3" cx="60" cy="60" r="47"/>
          <circle class="crm-ring" style="--i:4" cx="60" cy="60" r="58"/>
        </svg>
        <span class="crm-pct"></span>
      </div>
      <span class="crm-hint">Scrollez ici ↓</span>
    </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 280px;
  overflow: hidden;
  position: relative;
  background: rgb(10, 10, 15);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.crm-scene {
  position: relative;
  width: 100%;
  max-width: 430px;
  height: 260px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .08);
  background: #0d0d16;
  --p: 0
}

.crm-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  z-index: 3;
  scrollbar-width: thin
}

.crm-stage {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none
}

.crm-hint {
  position: absolute;
  right: 10px;
  bottom: 8px;
  z-index: 2;
  font-size: .6rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #8f8fb0;
  opacity: calc(1 - var(--p) * 3);
  pointer-events: none
}

.crm-scroll:focus-visible {
  outline: 2px solid #a78bfa;
  outline-offset: -2px
}

.crm-track {
  width: 100%
}

.crm-svg {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 200px;
  height: 200px
}

.crm-ring {
  fill: none;
  stroke-width: 5;
  stroke-linecap: round;
  stroke: oklch(75% .26 calc(280 + var(--i) * 26 + var(--p) * 120));
  stroke-dasharray: calc((88 + var(--i) * 69) * var(--p) * 1px) 1000px;
  transform-origin: 60px 60px;
  transform: rotate(calc(-90deg + var(--i) * 18deg * var(--p))) scale(calc(.72 + var(--p) * .28));
  opacity: calc(.35 + var(--p) * .65)
}

.crm-pct {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 1rem;
  font-weight: 800;
  color: #e7e5ff;
  letter-spacing: .08em
}

.crm-pct::after {
  content: attr(data-pct)
}
JavaScript
(function() {
  (function() {
    /* fx-0781 — Concentric Rings Morph : progression de scroll → variable CSS --p (rAF, passif) */
    var sc = document.getElementById('crmScroll');
    if (!sc) return;
    var host = sc.closest('.crm-scene');
    var raf = null;

    function update() {
      raf = null;
      var max = sc.scrollHeight - sc.clientHeight;
      var p = max > 0 ? sc.scrollTop / max : 0;
      host.style.setProperty('--p', p.toFixed(4));
      var pct = host.querySelector('.crm-pct');
      if (pct) pct.setAttribute('data-pct', Math.round(p * 100) + '%');
    }
    sc.addEventListener('scroll', function() {
      if (!raf) raf = requestAnimationFrame(update);
    }, {
      passive: true
    });
    update();
  })();
})();

Scroll Velocity Feedback

Les éléments réagissent à la vitesse de défilement : étirement et inclinaison dynamiques qui donnent de la matière au scroll, puis retour au net à l'arrêt.

💡 Idéal pour : galerie éditoriale, grille de projets, feed immersif, page « about » créative.

Scroll Velocity requestAnimationFrame Premium

Pinned Image Sequence

Un objet épinglé dont la rotation 360° est pilotée par le scroll, façon séquence produit Apple. Ici, un vrai modèle 3D (.glb auto-hébergé, chargé à la demande) tourne au défilement.

💡 Idéal pour : vue produit 360°, démontage/feature reveal, page de lancement, tutoriel visuel étape par étape.

Scroll Sticky CSS 3D Premium

Sticky Horizontal Reveal

Une section épinglée dont le contenu défile horizontalement au scroll vertical. Raconte une progression (process, timeline, étapes) de façon cinématique.

💡 Idéal pour : présentation de process/étapes, timeline, showcase portfolio, page produit narrative.

Scroll Sticky Horizontal Premium

Scroll Choreography Sequence

Orchestration multi-éléments : titre, texte, badges et CTA entrent en cascade sur la timeline de scroll, comme une scène qui se monte. Chaque élément a sa fenêtre de progression.

💡 Idéal pour : hero de landing qui s'assemble, présentation de fonctionnalités, storytelling de marque, section « manifeste ».

Scroll Timeline Stagger Premium

Questions fréquentes

Comment déclencher une animation au scroll en JavaScript ? +

Utilisez IntersectionObserver : créez un observer avec un threshold (ex: 0.1), observez vos éléments, et ajoutez une classe CSS quand ils entrent dans le viewport. C'est la méthode la plus performante — pas de listener sur scroll.

Comment créer un effet parallax en CSS ? +

La méthode la plus simple utilise background-attachment: fixed sur un background-image. Pour un parallax plus contrôlé, utilisez transform: translateY() avec un coefficient réduit base sur la position de scroll (via JS ou scroll-timeline CSS).

Qu'est-ce que scroll-timeline en CSS ? +

scroll-timeline est une API CSS native qui lie une animation à la position de scroll — sans JavaScript. Vous définissez animation-timeline: scroll() et l'animation progresse avec le scroll. Supporte par Chrome et Edge depuis 2024.

Comment faire une barre de progression de lecture ? +

Écoutez l'événement scroll, calculez le pourcentage : (scrollY / (document.height - window.height)) * 100, et appliquez-le comme width d'une barre fixée en haut. Ou utilisez scroll-timeline CSS pour zéro JavaScript.

Les animations au scroll impactent-elles les performances ? +

Avec IntersectionObserver : non, c'est asynchrone. Avec un listener scroll : potentiellement oui — utilisez passive: true et un throttle/debounce. Avec scroll-timeline CSS : non, c'est géré par le navigateur nativement.

Catégories similaires