Effets Scroll & Parallax
Animations scroll, parallax, scroll-driven CSS, scrollytelling, sticky et snap.
Mis à jour le
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
transformetopacity, et coupez les effets pourprefers-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
Fade Up
Éléments qui apparaissent en montant avec un fondu progressif via animation-timeline: view().
Page de l’effet →Voir le code source
<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>.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;
}
}/* CSS pur — aucun JavaScript requis */Scale In
Éléments qui grossissent depuis une taille réduite avec animation-timeline: view().
Slide In
Éléments glissant depuis la gauche et la droite en alternance via view().
Parallax
Effet de parallaxe ou l'arrière-plan bouge a vitesse différente via scroll(nearest).
Page de l’effet →Progress Reveal
Texte qui se remplit progressivement avec un gradient animé par scroll(nearest) et @property.
Stagger Cards
Cartes apparaissant en cascade avec animation-delay incremental et view().
Horizontal Scroll
Défilement horizontal avec scroll-snap pour une navigation fluide entre les éléments.
Page de l’effet →Rotate In
Cartes apparaissant avec rotation et scale via view() et animation-delay.
Page de l’effet →Blur Reveal
Effet de mise au point progressive avec blur(20px) animé vers blur(0) via view().
Counter Scroll
Compteurs animés qui s'incrémentent lorsqu'ils entrent dans la vue du conteneur.
Scroll-Driven Fade
Animation CSS native pilotée par le scroll avec animation-timeline: view() et entry range.
View Timeline Scale
Éléments qui s'agrandissent progressivement via animation-timeline: view() et cover range.
Scroll Progress Bar
Barre de progression sticky liée au scroll du conteneur via scroll(nearest).
Parallax Layers CSS
Couches se déplaçant a vitesses différentes via scroll(nearest) pour un effet de profondeur.
Rotate On Scroll
Élément effectuant une rotation de 720 degrés liée au scroll via scroll(nearest).
Slide In CSS Native
Slide gauche/droite natif CSS avec animation-timeline: view() et cover range.
Blur to Clear
Transition de blur(10px) a blur(0) pour un effet cinématographique via view().
Page de l’effet →Stagger Reveal CSS
Grille d'items avec animation-delay incremental CSS natif et view() pour un effet cascade.
Clip Path Reveal
Révélation progressive via clip-path: inset() animé par view() et cover range.
Page de l’effet →Color Change
Changement de couleur progressif (violet, rose, cyan, vert) lié au scroll via scroll(nearest).
Barre de progression
Scrollez pour voir la barre se remplir. Utilise animation-timeline: scroll() pour lier l'animation au défilement du conteneur.
Progress Bar
Barre de progression liée au scroll via animation-timeline: scroll(). Se remplit de 0% à 100% en CSS pur.
Page de l’effet →Voir le code source
<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>.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);
}
}/* CSS pur — aucun JavaScript requis */Fade In Reveal
Éléments qui apparaissent progressivement via animation-timeline: view() et animation-range: entry.
Parallax Layers
Couches parallaxes avec des vitesses différentes, pilotées uniquement par scroll() en CSS natif.
Scale on Scroll
Cartes qui grandissent de 70% à 100% en entrant dans la vue via animation-timeline: view().
Color Shift
Gradient de fond qui évolue à travers 5 palettes de couleurs en scrollant, via animation-timeline: scroll().
Page de l’effet →Text Reveal
Mots qui glissent depuis le bas et se révèlent progressivement au défilement avec view().
Page de l’effet →Rotate on Scroll
Forme géométrique avec rotation à 720° liée au scroll. Les bordures tournent en sens inverse.
Slide In Cards
Cartes qui glissent alternativement depuis la gauche et la droite avec view() et animation-range: entry.
Page de l’effet →Zoom & Blur
Cercle qui zoome et se défloute au centre du scroll, puis continue à zoomer et se refloute en sortant.
Page de l’effet →Horizontal Scroll
Scroll vertical converti en défilement horizontal des cartes via animation-timeline: 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.
Progress Bar
Barre de progression de lecture pilotée par animation-timeline: scroll(), zéro JavaScript.
Page de l’effet →Voir le code source
<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>.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);
}
}/* CSS pur — aucun JavaScript requis */Scroll Fade Gallery
Images qui apparaissent en fondu et s'agrandissent à l'entrée du viewport via animation-timeline: view().
Page de l’effet →Voir le code source
<div class="demo-preview">
<div class="fade-gallery-container">
<div class="scroll-spacer"></div>
<div class="fade-gallery-item"></div>
<div class="fade-gallery-item"></div>
<div class="fade-gallery-item"></div>
<div class="fade-gallery-item"></div>
<div class="fade-gallery-item"></div>
<div class="scroll-spacer"></div>
</div>
<span class="slr-scroll-hint">Scrollez pour voir l'effet</span>
</div>.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;
}
.scroll-spacer {
height: 60px;
}
.fade-gallery-container {
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
padding: 20px 12px;
}
.fade-gallery-item {
width: 80%;
margin: 24px auto;
aspect-ratio: 16/9;
border-radius: 10px;
opacity: 0;
transform: scale(0.8) translateY(20px);
animation: fadeScaleIn linear both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
/* Les fonds comptent les enfants du défileur : le premier enfant est l'espaceur,
les cinq blocs sont donc les enfants 2 à 6. */
.fade-gallery-item:nth-child(2) {
background: linear-gradient(135deg, #ec4899, #f43f5e);
}
.fade-gallery-item:nth-child(3) {
background: linear-gradient(135deg, #06b6d4, #3b82f6);
}
.fade-gallery-item:nth-child(4) {
background: linear-gradient(135deg, #10b981, #059669);
}
.fade-gallery-item:nth-child(5) {
background: linear-gradient(135deg, #f59e0b, #ea580c);
}
.fade-gallery-item:nth-child(6) {
background: linear-gradient(135deg, #6366f1, #8b5cf6);
}
@keyframes hintBounce {
0%,
100% {
transform: translateX(-50%) translateY(0);
}
50% {
transform: translateX(-50%) translateY(-4px);
}
}
@keyframes fadeScaleIn {
from {
opacity: 0;
transform: scale(0.8) translateY(20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}/* CSS pur — aucun JavaScript requis */Horizontal Scroll Section
Section défilant horizontalement lors du scroll vertical, pur CSS avec scroll-timeline.
Page de l’effet →Sticky Reveal Stack
Cartes s'empilant et se révélant une par une au scroll avec view() timeline.
Text Line Reveal
Chaque mot se colore progressivement lors du scroll via animation-range et view().
Page de l’effet →Zoom Into Content
Contenu démarrant dézoomé qui s'agrandit à 100% au scroll, effet d'ouverture cinématique.
Rotation on Scroll
Élément tournant proportionnellement à la position de scroll, effet cadran/boussole.
Page de l’effet →Path Drawing on Scroll
Tracé SVG se dessinant via stroke-dashoffset animé par le scroll, pur CSS.
Page de l’effet →Parallax Layers
Parallaxe multi-couches entièrement contrôlé par scroll() timeline, sans JS.
Page de l’effet →Snap Gallery with Progress
Galerie snap-scrolling avec barre de progression et dots liés au scroll, pur CSS.
Page de l’effet →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.
Progress Bar
Barre de progression horizontale qui se remplit proportionnellement au défilement du contenu.
Page de l’effet →Voir le code source
<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>.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;
}
}(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.
Page de l’effet →Reveal on Scroll
Les éléments apparaissent avec un fondu et un glissement vertical lorsqu'ils entrent dans la zone visible.
Page de l’effet →Sticky Horizontal
Défilement horizontal automatique simulant une navigation par panneaux, idéal pour présenter des étapes ou des projets.
Page de l’effet →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.
Page de l’effet →Zoom on Scroll
Un élément grossit progressivement avec le défilement, passant d'un petit objet à une vue plein écran.
Page de l’effet →Number Counter Scroll
Les compteurs s'animent de zéro à leur valeur cible proportionnellement à la position de défilement.
Page de l’effet →Timeline Scroll
Chronologie verticale interactive avec une ligne qui se dessine progressivement et des éléments qui apparaissent au défilement.
Page de l’effet →Image Sequence
Simulation d'animation image par image pilotée par le scroll, similaire aux pages produit Apple.
Page de l’effet →Scroll Snap Sections
Sections pleine hauteur avec accrochage magnétique et indicateur de pagination latéral.
Page de l’effet →Sticky Scroll
8 effets de scroll sticky et parallax avances.
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.
Sticky Image Change
Image sticky qui change pendant que le contenu défile avec des panneaux révélés via view().
Page de l’effet →Voir le code source
<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>.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;
}
}/* CSS pur — aucun JavaScript requis */Horizontal Scroll
Section a défilement horizontal avec snap pour naviguer entre les étapes du workflow.
Page de l’effet →Card Stack
Cartes qui s'empilent avec position sticky et animation view() dans le conteneur.
Page de l’effet →Progress Reveal
Barre de progression sticky avec items révélés progressivement via scroll(nearest) et view().
Split Screen Sticky
Visuel sticky avec SVG rotatif et contenu révélé par scroll via view() et scroll(nearest).
Page de l’effet →Zoom In Sticky
Élément qui zoome progressivement de scale(1) à scale(2.2) via scroll(nearest).
Page de l’effet →Text Highlight Scroll
Mots colorés séquentiellement au scroll avec JS scope au conteneur.
Page de l’effet →Layered Parallax
5 couches se déplaçant a vitesses différentes via scroll(nearest) pour un effet parallax complet.
Page de l’effet →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
Vertical Snap
Sections s'ancrant automatiquement au début via scroll-snap-type: y mandatory.
Page de l’effet →Voir le code source
<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>.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;
}
}/* CSS pur — aucun JavaScript requis */Horizontal Snap
Défilement horizontal avec ancrage automatique via scroll-snap-type: x mandatory.
Page de l’effet →Card Snap Carousel
Carrousel de cartes s'alignant au centre avec scroll-snap-align: center.
Page de l’effet →Mixed Content Snap
Sections de tailles différentes avec scroll-snap-type: y proximity pour flexibilité.
Page de l’effet →Snap + Progress
Snap vertical avec barre de progression et dots indicateurs via JS scope au conteneur.
Page de l’effet →Smooth Snap
Snap avec animations déclenchées par IntersectionObserver scope au conteneur.
Page de l’effet →3D Depth Gallery
Galerie immersive Three.js : la caméra plonge dans une pile d'images, crossfade fluide, fond qui prend la couleur dominante, parallaxe au curseur. Sensation de profondeur cinématique.
💡 Idéal pour : portfolio créatif, showcase produit, galerie d'études de cas, page « notre travail », storytelling au scroll.
Page de l’effet →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.
Page de l’effet →Voir le code source
<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>.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;
}(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();
});
})();
})();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.
Page de l’effet →Voir le code source
<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>.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%
}(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();
})();
})();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.
Page de l’effet →Voir le code source
<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>.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
}(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();
})();
})();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 ».
Page de l’effet →Voir le code source
<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>.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)
}(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();
})();
})();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.
Page de l’effet →Voir le code source
<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>.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)
}(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.
Page de l’effet →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.
Page de l’effet →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.
Page de l’effet →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 ».
Page de l’effet →