Scroll✨ Premium

Clip Path Reveal

Trois blocs de 91 px dans une boîte de 280 px qui défile sur 620 px, chacun révélé par clip-path: inset() vers inset(0) sur une timeline view(), plage entry → cover 60 % : le premier s'ouvre de gauche à droite, le deuxième de haut en bas, le troisième du bas vers le haut, sans fondu ni déplacement — le contenu est déjà là, c'est le cache qui s'ouvre, sur 223 px de défilement par bloc. CSS seul, zéro JavaScript.

CSSClip-pathReveal

Mis à jour le

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Scroll comprend 70 effets, dont 12 gratuits. Découvrir la catégorie →

3 exemples d'usage

Rendu d'une peinture au rouleau — fiche produit d'une peinture murale — Clip Path Reveal exemple 1

① Rendu d'une peinture au rouleau — fiche produit d'une peinture murale

QuandFiche d'une teinte : nom, prix au litre et bouton dans une colonne fixe, puis, dans la zone qui défile, trois aplats de rendu (mat, satiné, velours) qui se dévoilent de gauche à droite comme une passe de rouleau.
Pourquoiinset(0 100% 0 0) → inset(0) balaie horizontalement sans fondu : l'aplat apparaît à pleine couleur derrière l'arête du cache, exactement comme la peinture derrière le rouleau. Blur to Clear (fx-0551) ferait émerger la teinte d'un flou, ce qu'aucune peinture ne fait ; Fade Up (fx-0535) la ferait monter et pâlir.
RéglagesColonne fixe de 190 px, boîte défilante absolue à droite (350 × 360) ; plateau à height: auto, gap: 10px ; trois aplats de 104 px (teinte #b8623a, bande sombre en bas pour le texte, variantes satinée et velours) tous forcés à inset(0 100% 0 0) — les directions des :nth-child(2) et (3) sont écrasées ; plage inchangée, donc 278 px de défilement par aplat (0,6 × (360 + 104)) ; au repos, 1er ouvert, 2e à 69 %, 3e à 28 % ; course 268 px. Le défilement automatique est un artifice de démonstration.
Tableau des scores d'une finale e-sport — écran de la scène pendant la pause — Clip Path Reveal exemple 2

② Tableau des scores d'une finale e-sport — écran de la scène pendant la pause

QuandÉcran de présentation : titre de la finale, puis quatre lignes de score (équipe, éliminations, objectifs, points) dévoilées d'un bord à l'autre quand l'animateur fait défiler.
PourquoiUne ligne de score doit surgir entière et nette, pas monter ni fondre : le balayage clip-path se lit comme un « wipe » de régie, et la direction se règle ligne par ligne en CSS — la troisième s'ouvre par le bas, comme dans le code vendu, la quatrième par la droite.
RéglagesBarre de 56 px, boîte défilante de 304 px ; lignes = .sb-clippath-box en grille, 58 px de haut, fond #12152a, filet gauche à la couleur de l'équipe ; directions : 1re gauche → droite, 2e haut → bas, 3e bas → haut (code vendu), 4e droite → gauche par inset(0 0 0 100%) ajouté dans la scène ; 217 px de défilement par ligne, course 232 px ; au repos, 1re ouverte, 2e à 68 %, 3e à 37 %, 4e à 6 %.
Lever de rideau sur les créations de la saison — page « Saison » d'un théâtre municipal — Clip Path Reveal exemple 3

③ Lever de rideau sur les créations de la saison — page « Saison » d'un théâtre municipal

QuandPage de saison : nom du théâtre et billetterie dans la barre, puis, dans la zone qui défile, un édito et trois affiches de spectacle posées devant un rideau rouge, chacune dévoilée du bas vers le haut à mesure que le lecteur descend, comme le rideau qui se lève sur un décor déjà planté.
Pourquoiinset(100% 0 0) → inset(0) dévoile par le bas sans rien déplacer : l'affiche est entière derrière le cache dès le départ, seule l'arête du rideau monte — c'est exactement ce que fait un rideau de scène, le décor est planté avant que le public le voie. Fade Up (fx-0535) ferait monter l'affiche elle-même en s'éclaircissant, Blur to Clear (fx-0551) la ferait sortir d'un flou : aucun rideau ne fait l'un ni l'autre.
RéglagesBarre de 52 px, boîte défilante de 308 px ; plateau passé en ligne (flex-direction: row) de trois cadres de 160 × 200 px, fond rideau (repeating-linear-gradient à 90°, plis de 26 px) et tringle dorée en ::before ; l'affiche est le .sb-clippath-box, absolu sur tout le cadre, inset(100% 0 0) forcé sur les trois ; le cadre est rogné par clip-path: inset(0 round 6px), pas par overflow: hidden — mesuré : avec overflow: hidden, le cadre devient un conteneur de défilement, view() s'y accroche et l'affiche reste figée à inset(16.7% 0 0) ; 305 px de défilement par affiche (0,6 × (308 + 200)), course 318 px ; au repos, affiches posées à 165 px sous le haut de la boîte et dévoilées à 47 % ; les trois sont entières à 165 px de défilement. Le défilement automatique est un artifice de démonstration.

Comment ça marche

Le HTML vendu : le cadre .demo-preview (flex centré, min-height: 300px, position: relative, fond #0a0a0f, texte blanc), la boîte .sdc-scroll-container (100% × 280px, overflow-y: auto, scroll-behavior: smooth), le plateau .sb-clippath-content (colonne flex, gap: 30px, padding: 60px 16px, 900 px de haut), trois .sb-clippath-box (padding: 24px, border-radius: 16px, texte centré, dégradés à 90° de cinq, trois et trois arrêts) avec un h4 de 1,1 rem graisse 800 et un p de 0,75 rem en blanc à 90 %, et l'indice .sdc-scroll-hint « Scrollez ↓ » (absolu, 8 px du bas du cadre, blanc à 30 %, pulsant à 70 % toutes les 2 s). Mesuré à 1 280 px de large : boîtes de 91 px posées à 60, 181 et 302 px du haut du plateau, course 900 − 280 = 620 px. Champ JS vide, aucune variable var(--…), aucune erreur console ; l'unique style en ligne (pile Inter, -apple-system… sur chaque h4) ne charge rien : Inter absente, police système.

Un seul @keyframes sbClipReveal { to { clip-path: inset(0) } }, et chaque bloc le déclare en propriétés longues : animation-name, animation-timeline: view(), animation-range: entry cover 60%, animation-duration: auto, animation-timing-function: linear, animation-fill-mode: both. Le point de départ est le clip-path propre à chaque bloc : inset(0 100% 0 0) (masqué depuis la droite, donc ouverture de gauche à droite), inset(0 0 100%) sur :nth-child(2) (masqué depuis le bas, ouverture de haut en bas), inset(100% 0 0) sur :nth-child(3) (masqué depuis le haut, ouverture du bas vers le haut). Rien d'autre ne bouge : opacité 1 et transform: none relevés à chaque position. view() sans argument prend le conteneur défilant le plus proche, ici la boîte de 280 px, sur l'axe des blocs ; la plage entry → cover 60% démarre quand le haut du bloc touche le bas de la boîte et s'achève à 60 % de sa traversée complète, soit 0,6 × (280 + 91) ≈ 223 px de défilement par bloc — le cache finit de s'ouvrir quand le haut du bloc est à 57 px du haut de la boîte. Tracé linéaire : le balayage horizontal parcourt 1 232 px de largeur en 223 px de molette (5,5 px par pixel défilé), les verticaux 91 px (0,4 px par pixel). inset(0 100%0 0) est écrit sans espace dans le code vendu (reste de minification) : le tokeniseur coupe 100%0 en 100% puis 0, mesuré valide dans Chromium, Firefox et WebKit — écrivez 100% 0 si vous le retouchez.

Mesuré dans Chromium, boîte au repos : le premier bloc, posé à 60 px, a déjà parcouru 220 des 223 px de sa plage — inset(0 1.17% 0 0), 14 px encore masqués à droite ; le deuxième est ouvert à 44 % (inset(0 0 55.5%), 40 px visibles sur 91) ; le troisième, à 302 px, n'est pas encore entré : inset(100% 0 0), invisible. À 60 px de défilement : 100 / 71 / 17 % ; à 120 : 100 / 98 / 44 % ; à 180 : 100 / 100 / 71 % ; à 240 : 98 % pour le troisième ; à 300 px, soit 48 % de la course, les trois sont à inset(0). Remonter referme les caches dans l'autre sens (la progression suit le défilement, pas le temps). De 393 à 620 px, le dernier bloc est sorti par le haut et la boîte n'affiche que son fond : 227 px de course vide, conséquence des 900 px fixés sur le plateau. Le cadre apporte son propre fond sombre, donc l'effet se lit sur une page blanche ; ni id ni script : deux copies sur la même page cohabitent. scroll-behavior: smooth n'agit que sur les positions programmées : scrollTop = 300 se relit 1 puis arrive en 264 ms ; la molette, elle, est instantanée.

Accessibilité

  • prefers-reduced-motion absent du code : mesuré sous émulation, mêmes valeurs de clip-path à chaque position et indice toujours pulsant. Le balayage est piloté par le lecteur (rien ne bouge sans lui, hormis l'indice) et ne déplace aucun contenu — seule l'arête d'un cache avance —, ce qui le range parmi les animations déclenchées par l'interaction (WCAG 2.3.3), sans composante vestibulaire. Pour montrer tout à plat quand la préférence est active, ajoutez @media (prefers-reduced-motion: reduce) { .sb-clippath-box { animation: none; clip-path: inset(0) } .sdc-scroll-hint { animation: none } }.
  • Clavier : Chromium et Firefox donnent le focus à la boîte par Tab sans tabindex (mesuré : activeElement = .sdc-scroll-container) ; WebKit non (focus resté sur body, flèche bas sans effet). Ajoutez tabindex="0" et un :focus-visible visible sur .sdc-scroll-container. Une fois la boîte focalisée : flèche bas = 40 px (18 % d'un balayage), PageDown = 285 px (les trois blocs ouverts d'un coup), Fin = 620. Au doigt, le geste doit commencer dans la boîte ; overscroll-behavior: contain évite d'entraîner la page en bout de course.
  • Contraste : le h4 blanc de 17,6 px (sous le seuil « grand texte ») vaut 3,7:1 sur le rose, 2,1:1 sur l'ambre, 2,3:1 sur le vert et 2,4:1 sur le cyan du premier dégradé ; seul l'indigo du deuxième atteint 4,5:1 ; le p de 12 px en blanc à 90 % tombe entre 2,0:1 et 3,9:1. Aucun bloc livré n'est conforme sur toute sa largeur : assombrissez les dégradés ou posez le texte sur une bande sombre, comme les trois scènes de cette page. L'indice à 30 % vaut 2,6:1 au repos, de 1,2:1 à 1,8:1 sous la pulsation : l'opacité animée (.3 → .7) se multiplie à celle de la couleur.
  • Lecteurs d'écran et repli : clip-path ne retire rien de l'arbre d'accessibilité — les trois blocs sont lus en entier, masqués ou non, et rien n'est à annoncer. Trois h4 sans h2/h3 au-dessus cassent le plan de la page : prenez le niveau qui suit votre titre courant. L'indice « Scrollez ↓ » est en français quelle que soit la langue de la page : posez aria-hidden="true" dessus ou retirez-le. Là où animation-timeline n'existe pas (Firefox, mesuré), les trois blocs sont à inset(0) dès le chargement : tout est lisible, à plat, tant que animation-fill-mode: both reste en place (voir « Mode de remplissage »).

Compatibilité navigateur

CSS seul, zéro JavaScript, zéro dépendance. Trois propriétés récentes : animation-timeline: view(), animation-range et animation-duration: auto — Chrome et Edge 115, Safari 26 et iOS 26. Le reste est ancien : clip-path: inset(), flexbox, dégradés, scroll-behavior, ::-webkit-scrollbar (Blink et WebKit seulement, Firefox garde sa barre native). Firefox : aucune version ne rend les animations pilotées au défilement. Mesuré sur le code vendu, page vierge : CSS.supports('animation-timeline: view()') faux, et les trois blocs affichés en entier dès le repos (inset(0)), avant tout défilement — la boîte défile, l'indice pulse, aucun cache ne s'ouvre : le visiteur Firefox voit trois cartes colorées, à plat, complètes et lisibles. Pas de repli @supports dans le code : il n'en a pas besoin, l'état final est le contenu entier.

Chrome 115+✓ Complet
Firefox✓ Aucune version : blocs entiers dès le chargement, sans balayage (mesuré)
Safari 26+✓ Complet (mesuré dans WebKit : mêmes valeurs qu'en Chromium)
Edge 115+✓ Complet
Mobile iOS 26+✓ Complet (défilement tactile de la boîte)
Android Chrome 115+✓ Complet

Sans animation-timeline (Firefox, Chrome et Edge avant 115, Safari avant 26) : animation-duration: auto est ignoré, la durée retombe à 0 s, l'animation est finie avant le premier rendu et animation-fill-mode: both laisse la dernière image, inset(0) — blocs entiers, sans balayage, boîte qui défile comme une zone ordinaire. Sans ::-webkit-scrollbar, barre du système ; sans scroll-behavior, défilements programmés sans lissage. Aucun script : rien à perdre.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :

index.html — structure
<div class="demo-preview">
  <div class="sdc-scroll-container">
    <div class="sb-clippath-content">
      <div class="sb-clippath-box">
        <h4>…</h4>
        <p>…</p>
      </div>
      <div class="sb-clippath-box">
        <h4>…</h4>
        <p>…</p>
      </div>
      <div class="sb-clippath-box">
        <h4>…</h4>
        <p>…</p>
      </div>
    </div>
  </div>
  <span class="sdc-scroll-hint">…</span>
</div>
Débloquer le code complet — 9,90 € HT/mois

Le code complet HTML + CSS + JS de Clip Path Reveal, prêt à coller — et les 811 effets. Ou 299 € une fois, accès à vie.

Personnaliser

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

Option / propriétéDéfautEffet
Direction d'ouverture (CSS — clip-path de départ sur .sb-clippath-box, :nth-child(2), :nth-child(3)) inset(0 100% 0 0) / inset(0 0 100%) / inset(100% 0 0) Le côté à 100 % est celui qui masque : inset(0 0 0 100%) ouvre de droite à gauche (4e ligne de la scène e-sport), inset(0 50%) ouvre depuis le centre vers les deux bords, inset(50% 0) depuis la ligne médiane. Un round 16px après les valeurs garde les coins arrondis pendant le balayage ; la fin, inset(0), est commune aux trois.
Plage (CSS — animation-range: entry cover 60%) entry → cover 60 % (223 px par bloc) Longueur du balayage = 60 % de la traversée, soit 0,6 × (hauteur de la boîte + hauteur du bloc). entry seul (= entry 0% entry 100%) finit quand le bloc est tout juste entré : 91 px ici, 2,5 fois plus vif. entry 20% cover 60% retarde le départ, ce qui évite qu'un bloc placé haut dans le plateau soit déjà ouvert au repos.
Timeline (CSS — animation-timeline: view()) view() — conteneur défilant le plus proche, axe des blocs view(inline) suit un défilement horizontal ; view(block 20% 0) rétrécit la zone de visibilité et retarde l'entrée ; scroll() lie les trois blocs à la progression de toute la boîte et les ouvre ensemble. Attention : tout ancêtre en overflow: hidden devient la référence de view() et fige l'animation (mesuré dans la scène du théâtre).
Hauteurs (CSS — .sdc-scroll-container { height: 280px }, .sb-clippath-content { height: 900px; padding: 60px 16px; gap: 30px }) 280 px / 900 px (course 620 px, dont 227 vides) La hauteur de la boîte entre dans la longueur du balayage ; celle du plateau fait la course. À height: auto, le plateau mesure 453 px et la course 173 : le dernier bloc ne s'ouvre plus qu'à 88 % — gardez un padding-bottom d'au moins 280 px ou du contenu sous les blocs.
Tracé (CSS — animation-timing-function: linear) linear Avec une timeline de défilement, la fonction transforme la position en progression : ease-out ouvre vite puis freine, ease-in l'inverse, steps(8) découpe le balayage en huit crans. Le rythme reste dicté par la main du lecteur.
Mode de remplissage (CSS — animation-fill-mode: both) both Indispensable des deux côtés : dans un navigateur qui comprend la timeline, none rendrait au bloc son clip-path de départ une fois la plage dépassée — il disparaîtrait après s'être ouvert ; dans un navigateur qui ne la comprend pas, c'est both qui tient l'image finale inset(0) (mesuré dans Firefox). forwards suffit pour les deux cas.
Indice « Scrollez ↓ » (CSS — .sdc-scroll-hint, @keyframes sdcHintPulse) 8 px du bas du cadre, blanc à 30 %, pulsation 2 s Français en dur, absolu par rapport à .demo-preview — sans ce cadre en position: relative, il tombe au bas de la page. Pour le retirer, supprimez le span et la @keyframes ; pour le garder, traduisez-le et posez aria-hidden="true".

FAQ

Oui, et c'est mesuré : Firefox ne rend les animations pilotées au défilement dans aucune version. Il ignore animation-timeline: view() et animation-duration: auto, la durée retombe à 0 s et animation-fill-mode: both conserve la dernière image, inset(0) : les trois cartes sont affichées en entier dès le chargement, la boîte défile, l'indice pulse. Rien n'est perdu ni caché, seul le balayage manque — d'où l'absence de repli @supports. Si le balayage vous est indispensable partout, il faut le piloter en JavaScript (un IntersectionObserver ou un écouteur scroll qui écrit clip-path), ce que cet effet ne fait pas ; sinon, acceptez un rendu à plat pour 3 à 4 % des visiteurs.
Par géométrie. La plage démarre quand le haut du bloc touche le bas de la boîte et dure 223 px ; le premier bloc est posé à 60 px (le padding-top), il a donc déjà parcouru 220 de ses 223 px au repos — inset(0 1.17% 0 0), 14 px encore masqués. Le troisième est à 302 px, sous le bord de la boîte : pas entré, masqué à 100 %, complet seulement à 300 px de défilement, alors que la course en fait 620 dont 227 vides. Pour que le premier bloc balaie lui aussi sous les yeux du lecteur, posez-le sous la ligne de flottaison (padding-top: 280px) ou retardez le départ avec animation-range: entry 20% cover 60% ; pour supprimer la course vide, passez le plateau en height: auto avec un padding-bottom suffisant.
Le même cache, deux moteurs. fx-0652 anime un seul mot, « REVEAL » en 2,5 rem graisse 800, de inset(0 100% 0 0) à inset(0) par une animation temporelle : animation: 1s ease 0s 1 normal forwards clipRevealAnim — elle se joue une fois, au chargement, en une seconde, quelle que soit la position de défilement, et fonctionne partout, Firefox compris. fx-0553 remplace le temps par la position : animation-timeline: view() lie chaque bloc à son entrée dans la boîte, la progression suit la molette dans les deux sens, et trois directions d'ouverture coexistent (droite, haut, bas) — au prix de Chrome 115 / Safari 26 comme plancher et d'un rendu à plat dans Firefox. Choisissez selon le déclencheur : un titre qui doit se révéler à l'arrivée sur la page, fx-0652 ; des blocs qui doivent se révéler quand le lecteur les atteint, fx-0553.