ScrollGratuit

Vertical Snap

Quatre sections de 280 px dans une boîte de 280 px à overflow-y: auto : scroll-snap-type: y mandatory arrête chaque geste sur un début de section, scroll-behavior: smooth lisse les sauts programmés. Deux règles, zéro JavaScript, zéro dépendance : un cadre .sn-vsnap-wrap porte le fond, la police et l'indice « Scrollez ↓ », et box-sizing: border-box garde chaque section à 280 px, padding compris (mesuré : course 840, une section = une fenêtre).

CSSSnapVertical

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 ↓
Survolez ou cliquez la scène pour interagir

Cet effet est gratuit — la catégorie Scroll en contient 70 au total, dont 12 gratuits. Effect.Labs regroupe 811 effets vanilla. Découvrir la catégorie →

Exemples d'usage

Lumen — Équipe produit
à moi · aujourd'hui, 09:12
Trois nouveautés dans Lumen 4.2
Faites défiler le bloc ci-dessous : une nouveauté par écran.
1/3 ↓

Automatisation

Des règles qui déclenchent vos flux toutes seules : formulaire reçu, forfait changé, échéance atteinte.

2/3 ↓

Reporting

Des rapports hebdomadaires construits sur vos propres vues, envoyés en PDF à qui vous voulez.

3/3

Intégrations

Slack, HubSpot, Notion et 40 autres outils se branchent en deux clics, sans clé d'API à copier.

Découvrir la mise à jour

① Slides embarqués dans un email interactif — trois fonctionnalités qui snappent sans une ligne de script

QuandEmail HTML d'un éditeur de logiciels qui annonce une mise à jour : en-tête expéditeur, objet, puis un bloc de trois diapositives (Automatisation, Reporting, Intégrations) que le lecteur fait défiler, et un bouton en dessous.
PourquoiLes clients mail bloquent le JavaScript ; les trois autres snaps du lot (fx-0584, fx-0597, fx-0598) dépendent d'un script pour leurs points, leur barre ou leurs animations d'entrée et n'y font rien. Ici deux règles CSS suffisent dans les clients qui rendent le CSS embarqué (Apple Mail, Outlook Web), et là où un client les ignore, les trois diapositives s'empilent et se lisent quand même.
RéglagesBoîte de 172 px, sections à height: 100% (le box-sizing: border-box du code vendu conservé), scroll-snap-stop: always (un geste = une diapositive), compteur « 1/3 ↓ » écrit en dur dans chaque diapositive faute de script, scrollbar-width: thin, fond clair et accent #4f46e5 ; l'indice « Scrollez ↓ » remplacé par ce compteur. Les diapositives avancent seules jusqu'au premier geste — un artifice de démonstration, pas une capacité de l'email.
Guide › Démarrage rapide

Démarrage rapide

Trois étapes, une commande chacune. Faites défiler le bloc.

Étape 1 sur 3

Installation

$npm install -g orbit-cli

Node 20 ou plus récent. Le binaire est ajouté à votre PATH.

Étape 2 sur 3

Configuration

$orbit init --region eu-west-3

Écrit orbit.config.json à la racine du projet.

Étape 3 sur 3

Déploiement

$orbit deploy --prod

Construit, envoie et bascule l'URL, en une minute environ.

② Composant de documentation statique généré — Installation, Configuration, Déploiement en trois écrans

QuandSite de documentation technique produit par Eleventy ou Hugo : barre latérale, article, et dans l'article un composant « étapes » dont chaque écran montre une commande et sa note.
PourquoiZéro runtime : le composant est un partial Nunjucks ou un shortcode Hugo avec deux règles CSS, sans bundler ni script à charger — fx-0584 et fx-0598 exigent un script que ces générateurs n'embarquent pas sans configuration. La page reste indexable et lisible sans JS, ce qu'une documentation doit être.
RéglagesBoîte de 196 px, sections à height: 100% alignées à gauche (align-items: flex-start par-dessus le centrage du code vendu), scroll-snap-type: y mandatory et scroll-behavior: smooth conservés, numéro d'étape, commande en ui-monospace, thème sombre ; barre de défilement laissée visible pour dire qu'on peut faire défiler.
Règlement de compétition · Saison 2026-27 2e mi-temps · 63:12
Article 12

Fautes et incorrections

Un coup franc direct est accordé lorsqu'un joueur commet une faute de manière imprudente, inconsidérée ou avec excès d'engagement. L'imprudence vaut avertissement, l'excès d'engagement l'exclusion.

Article suivant ↓
Article 13

Coups francs

Le ballon est en jeu dès qu'il est botté et bouge clairement. Les adversaires restent à 9,15 m du ballon jusqu'à ce qu'il soit en jeu.

Article suivant ↓
Article 14

Coup de pied de réparation

Le tireur est identifié, le gardien reste sur sa ligne jusqu'à la frappe, tous les autres joueurs hors de la surface et à 9,15 m du point.

Retour à l'article 12 ↓

③ Règlement sportif article par article sur tablette terrain — un article par écran, le pouce fait le reste

QuandUn arbitre consulte le règlement de la compétition sur sa tablette pendant le match : en-tête avec le chrono, un article par écran, le pouce vers le haut passe au suivant.
PourquoiPas un octet de JavaScript à charger ni à exécuter : rien ne casse si le réseau tombe ou si la tablette Android a cinq ans — fx-0597 (JS + barre de progression) peut échouer en silence si IntersectionObserver manque. Le snap garantit qu'un article entier est à l'écran, jamais deux moitiés.
RéglagesBoîte calée sous un en-tête de 44 px (position: absolute; top: 44px; bottom: 0), sections à height: 100%, scroll-snap-stop: always, overscroll-behavior: contain, texte de 14 px sur fond sombre pour l'extérieur, accent #4ade80, mention « Article suivant ↓ » en dur dans chaque article ; en production, boîte à 100dvh.

Comment ça marche

Un cadre .sn-vsnap-wrap en position: relative, fond #1e1b4b, texte blanc, police Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif. Dedans, la boîte .sn-vsnap-container fait 100% × 280px, overflow-y: auto, scroll-snap-type: y mandatory et scroll-behavior: smooth. Elle contient quatre .sn-vsnap-section de 280px en box-sizing: border-box avec scroll-snap-align: start : à la fin de chaque geste, le navigateur termine le défilement sur le haut de la section la plus proche — mandatory interdit toute position de repos entre deux. Chaque section est une colonne flex centrée (gap: 8px, padding: 20px) avec un h4 de 0.9rem en blanc et un p de 0.72rem en blanc à 60 %, sur quatre dégradés à 135° qui vont de #1e1b4b → #312e81 à #6d28d9 → #7c3aed, de l'indigo au violet. Après la boîte, un span.sdc-scroll-hint « Scrollez ↓ » en position: absolute s'accroche au cadre (mesuré : offsetParent = .sn-vsnap-wrap, 8 px au-dessus du bas de la boîte, centré) et pulse de 30 % à 70 % d'opacité toutes les 2 s. Le champ JS du code vendu tient en un commentaire : c'est le moteur de défilement qui fait tout.

La ligne box-sizing: border-box sur .sn-vsnap-section n'est pas décorative. Sans elle, les 20px de padding s'ajouteraient aux 280px et chaque section ferait 320 px dans une fenêtre de 280 px (mesuré en la retirant : scrollHeight 1280, course 1000 au lieu de 840, texte 20 px sous le centre visible). Quand une zone de snap dépasse le port, la spécification autorise toute position où elle le couvre encore : chaque section aurait une bande libre de 40 px dans laquelle le snap retiendrait sans basculer — un cran de molette de 100 px se poserait à 40, la flèche bas aussi, un cran de 600 px atterrirait à 640 et le bas de chaque diapositive serait coupé de 40 px. Avec la ligne, mesuré dans Chromium, pointeur sur la boîte : sections de 280, course 840, texte centré au pixel ; un cran de 100 px monte à 82 puis revient à 0 (le snap va au plus proche : il faut dépasser la moitié d'une section, 140 px, en un seul geste — 150 px se pose à 280), deux crans de 100 px rapprochés font 280, un cran de 600 px va à 560, section 3, en sautant la 2 (pas de scroll-snap-stop).

Le geste n'est pas lu pareil partout. Mesuré sur le code vendu, page vierge, boîte au repos : Chromium retient le cran de 100 px (retour à 0) là où Firefox 153 et WebKit 26 avancent d'une section (280) ; à 600 px, Chromium va à 560, Firefox à 280 (une section par geste, quelle que soit l'amplitude) et WebKit file en fin de course, 840. scroll-behavior: smooth ne concerne que les défilements programmés ou par ancre : un scrollTop = 280 atteint 280 en 274 ms dans Chromium, 199 ms dans WebKit et 579 ms dans Firefox, et s'y pose sans dépassement ; la molette, elle, est lissée par l'animation de snap du moteur. Deux choix d'écriture découlent de l'autonomie du code. Le fond #1e1b4b du cadre est la couleur de départ du premier dégradé : les dégradés sont posés sur les sections, le cadre garde la boîte sombre sur une page blanche et là où un client mail ne rend pas linear-gradient. La police est déclarée une seule fois, sur le cadre, et héritée par les titres, les paragraphes et l'indice : Inter n'est pas chargée par l'effet, le navigateur passe donc au maillon suivant de la pile (mesuré : system-ui dans Chromium) — chargez Inter dans votre page si vous la voulez, ou remplacez la pile par la vôtre.

Accessibilité

  • prefers-reduced-motion absent du code : sous la préférence, scroll-behavior calcule toujours smooth (mesuré dans Chromium : scrollTop = 280 met encore 271 ms) et l'indice continue de pulser (animation mesurée running). Ajoutez @media (prefers-reduced-motion: reduce) { .sn-vsnap-container { scroll-behavior: auto } .sdc-scroll-hint { animation: none } }. Le snap lui-même n'est pas une animation mais une position d'arrêt : il reste actif, et c'est acceptable (WCAG 2.3.3 vise le mouvement, pas l'alignement).
  • Clavier : Chromium et Firefox donnent le focus à la boîte par Tab (mesuré : activeElement = .sn-vsnap-container), WebKit non (focus resté sur body, flèche bas sans effet). Ajoutez tabindex="0", un aria-label (« Quatre sections, défilement vertical ») et un style :focus-visible — l'anneau de focus par défaut de Chromium entoure toute la boîte. Une fois la boîte focalisée : flèche bas = section suivante (mesuré 280 puis 560), flèche haut revient à 280, Page suivante va à 280, Fin à 840, Début à 0.
  • Contraste (texte de 11,5 px, seuil 4,5:1) : le paragraphe en blanc à 60 % vaut 6,5:1 sur #1e1b4b mais 3,5:1 sur #6d28d9 et 3,0:1 sur #7c3aed — la section 4 échoue. Passez l'opacité à 80 % (rgba(255,255,255,.8)) ou éclaircissez moins le dernier dégradé. Les titres blancs tiennent partout (5,7:1 au pire). L'indice à 30 % vaut 1,7 à 2,6:1, et 3,6 à 8,4:1 au sommet de sa pulsation : posez aria-hidden="true" dessus, il est décoratif.
  • Lecteurs d'écran et repli : quatre div avec un h4 chacun — le niveau 4 sans h2/h3 au-dessus casse le plan de la page ; prenez le niveau qui suit votre titre courant, ou des section aria-labelledby. mandatory interdit tout repos entre deux sections : si une section peut dépasser la hauteur de la boîte (texte zoomé à 200 %, contenu variable), préférez proximity — avec mandatory, le bas d'une section plus haute que la boîte n'est atteignable que dans la bande où elle couvre encore la fenêtre, et le snap y retient chaque cran (c'est exactement ce que la ligne box-sizing évite pour les sections livrées). Au doigt, le défilement est celui du navigateur (aucun écouteur) ; overscroll-behavior: contain évite d'entraîner la page quand on arrive au bout de la boîte.

Compatibilité navigateur

CSS seul : scroll-snap-type et scroll-snap-align (syntaxe moderne), scroll-behavior, overflow-y, flexbox, linear-gradient, @keyframes. Zéro dépendance, zéro JavaScript. C'est du CSS classique, pas une animation pilotée par animation-timeline : le snap fonctionne dans Firefox (mesuré dans Firefox 153 — même géométrie, mêmes arrêts), là où les défilements en animation-timeline n'y fonctionnent dans aucune version.

Chrome 69+✓ Complet
Firefox 68+✓ Complet
Safari 15.4+✓ Complet (11 à 15.3 : snap sans lissage programmé)
Edge 79+✓ Complet
Mobile iOS 15.4+✓ Complet (11+ : snap seul)
Android Chrome 69+✓ Complet

Sans prise en charge du snap (avant Chrome 69, Firefox 68, Safari 11), la boîte reste une zone de 280 px qui défile librement : les sections s'enchaînent sans arrêt automatique. Sans scroll-behavior, seuls les défilements programmés perdent leur lissage — la molette et le doigt ne sont pas concernés. Là où overflow n'est pas honoré (certains clients mail), les quatre sections s'empilent à leur hauteur : tout reste lisible, sans diapositives ; et là où les dégradés ne sont pas rendus, le fond #1e1b4b du cadre garde le texte blanc lisible.

Le code

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

HTML
<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>
CSS
/* Cadre de l'effet : son fond, sa police et l'ancre de l'indice « Scrollez ↓ ».
   Sans fond déclaré, le texte blanc disparaît sur une page claire. */
.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; /* le padding compte dans les 280 px : une section = une fenêtre */
   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, rgb(30, 27, 75), rgb(49, 46, 129));
   }

.sn-vsnap-section:nth-child(2)  {
   background: linear-gradient(135deg, rgb(49, 46, 129), rgb(76, 29, 149));
   }

.sn-vsnap-section:nth-child(3)  {
   background: linear-gradient(135deg, rgb(76, 29, 149), rgb(109, 40, 217));
   }

.sn-vsnap-section:nth-child(4)  {
   background: linear-gradient(135deg, rgb(109, 40, 217), rgb(124, 58, 237));
   }

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

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

.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: 2s ease-in-out 0s infinite normal none running sdcHintPulse;
   }

@keyframes sdcHintPulse  {
   
  0%, 100%  {
   opacity: 0.3;
   }
  50%  {
   opacity: 0.7;
   }
}
JavaScript (fx-0593)
// Effet CSS pur — pas de JavaScript nécessaire

Personnaliser

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

Option / propriétéDéfautEffet
Hauteur de la boîte et des sections (CSS — .sn-vsnap-container, .sn-vsnap-section) 280px / 280px, padding compris (box-sizing: border-box) Les deux doivent être égales pour qu'une section remplisse la fenêtre ; le border-box de la section garde les 20 px de padding à l'intérieur des 280 px. Pour que les sections suivent la boîte quelle que soit sa hauteur, passez-les à height: 100%. Mesuré sans le border-box : sections de 320 px, bande libre de 40 px par section, course 1000 au lieu de 840.
Fond et police du cadre (CSS — .sn-vsnap-wrap) #1e1b4b, Inter puis police système Le fond est la couleur de départ du premier dégradé : il garde le texte blanc lisible sur une page claire et là où les dégradés ne sont pas rendus ; alignez-le sur votre premier dégradé si vous changez les couleurs. Inter n'est pas chargée par l'effet : ajoutez-la à votre page ou remplacez la pile par celle de votre site.
scroll-snap-type (CSS — .sn-vsnap-container) y mandatory y proximity ne retient que près d'un début de section et laisse le repos ailleurs — plus sûr si une section peut dépasser la boîte. x mandatory avec des sections côte à côte donne le même snap à l'horizontale.
scroll-snap-align (CSS — .sn-vsnap-section) start center aligne le centre de la section sur celui de la boîte (utile si les sections sont plus petites que la boîte), end son bas.
scroll-snap-stop (CSS — à ajouter sur .sn-vsnap-section) absent (normal) always interdit de sauter une section en un geste : mesuré sans, un cran de 600 px passe de la section 1 à la 3. C'est la seule différence de CSS avec Smooth Snap (fx-0598).
scroll-behavior (CSS — .sn-vsnap-container) smooth Ne lisse que les défilements programmés (scrollTo, scrollTop, ancres) : mesuré 300 ms pour une section dans Chromium, instantané avec auto. La molette et le doigt sont lissés par le moteur quoi qu'il arrive.
Nombre et fonds des sections (HTML + CSS — :nth-child(1) à (4)) 4 sections, 4 dégradés à 135° Une cinquième section n'a pas de fond : ajoutez sa règle :nth-child(5) ou remplacez les quatre par une seule couleur. Les dégradés vont de #1e1b4b à #7c3aed ; à partir de #6d28d9 le paragraphe à 60 % passe sous 4,5:1.
Indice « Scrollez ↓ » (CSS — .sdc-scroll-hint) 8 px du bas, centré, pulsation 2 s de 30 à 70 % S'accroche au cadre .sn-vsnap-wrap (position: relative) : mesuré 8 px au-dessus du bas de la boîte, centré, par-dessus la section visible. Pour le déplacer, changez bottom et left ; pour le retirer, supprimez le span — la @keyframes sdcHintPulse part avec lui.
scroll-padding-top (CSS — à ajouter sur .sn-vsnap-container) absent Décale le point d'arrêt sous un en-tête collant : scroll-padding-top: 56px pour une barre de 56 px, sinon elle masque le haut de chaque section.

FAQ

Pourquoi un cran de molette ne passe-t-il pas à la section suivante ?

Parce que le snap se calcule à la fin du geste, vers la position valide la plus proche, et qu'un cran de 100 px ne fait pas la moitié d'une section de 280 px. Mesuré dans Chromium : 100 px → 82 → retour à 0 ; 150 px → 280 ; deux crans de 100 px rapprochés → 280. Il faut plus de 140 px en un seul geste (une impulsion de pavé tactile suffit). Les moteurs diffèrent : Firefox 153 et WebKit 26 avancent d'une section dès le premier cran de 100 px (mesuré 280), et à 600 px Firefox reste à 280 quand WebKit file à 840. Pour un comportement « un cran = une section » partout, il faut du JavaScript (écouter wheel et appeler scrollTo) — c'est justement ce que cet effet ne fait pas.

Quelle différence avec Smooth Snap (fx-0598), Scroll Snap Sections (fx-0584) et Snap + Progress (fx-0597) ?

Le cœur CSS est le même dans les quatre : boîte de 280 px, overflow-y: auto, scroll-snap-type: y mandatory, scroll-behavior: smooth, sections en scroll-snap-align: start. Smooth Snap ajoute scroll-snap-stop: always et un IntersectionObserver (seuil 0,6) qui pose .in-view sur la section visible pour animer son icône et son titre. Scroll Snap Sections ajoute un écouteur scroll qui calcule Math.round(scrollTop / 280) et allume le point correspondant. Snap + Progress ajoute une barre de progression en largeur, cinq points cliquables et un scrollTo programmé. Vertical Snap est le socle nu : choisissez-le quand le JavaScript n'est pas disponible (email, générateur statique, kiosque) ou quand vous écrirez vous-même l'indicateur ; prenez un voisin quand vous voulez ses points ou ses animations sans les coder.

Peut-on appliquer le snap à la page entière plutôt qu'à une boîte de 280 px ?

Oui : posez scroll-snap-type: y mandatory sur html (le conteneur de défilement de la page) et donnez aux sections min-height: 100vh100dvh sur mobile, pour suivre la barre d'adresse — avec scroll-snap-align: start. Trois précautions : scroll-padding-top égal à la hauteur d'un en-tête fixe, sinon il couvre le haut de chaque section ; proximity plutôt que mandatory dès qu'une section peut dépasser l'écran (texte zoomé, petit écran en paysage), car la page ne pourra plus se reposer au milieu ; et, si vous gardez l'indice « Scrollez ↓ », passez-le en position: fixed — accroché au cadre, il descendrait au bas du document, pas de l'écran. La molette n'est pas plus « stricte » qu'en boîte : mesuré, le même snap au plus proche s'applique.