Parallax Layers
Une scène de nuit dessinée en CSS (étoiles, lune, crêtes en triangles de bordure, brume, sol) épinglée par position: sticky dans un défileur de 280 px : sur une course de 1 400 px, cinq plans glissent sur la timeline nommée --parallaxScroll, de 40 px d'amplitude pour les étoiles à 160 px pour la brume. Zéro JavaScript ; Firefox voit la scène à plat.
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



Comment ça marche
Le HTML vendu emboîte trois cadres et cinq plans. Le cadre .demo-preview (flex centré, min-height: 300px, position: relative, fond #0a0a0f) contient le défileur .parallax-container (100% × 280 px, overflow: hidden auto, scroll-timeline: --parallaxScroll y), qui contient la piste .parallax-scene (height: 600%, soit 1 680 px), qui contient le viewport .parallax-viewport (position: sticky; top: 0, 280 px, overflow: hidden). La course vaut 1 680 − 280 = 1 400 px et le viewport, collé au haut du défileur, ne quitte jamais le cadre (mesuré : bord haut constant du premier au dernier pixel). Dedans, cinq plans en position: absolute : .parallax-stars (100 % du viewport, huit .p-star blanches de 2 px — deux de 3 px — entre 5 et 30 % du haut, opacités .3 à .8), .parallax-moon (30 px, top: 20px; right: 30px, dégradé radial #e0e7ff → #a5b4fc, halo de 20 px), puis trois bandes ancrées en bas par .slr-parallax-layer (bottom: 0) : .slr-parallax-bg (180 px de dégradé indigo, dont les deux crêtes sont des triangles de bordure de 280 × 140 px à left: -10% et 240 × 110 px à right: -5%), .parallax-mid (120 px, dont le ::before de 80 px porte deux dégradés radiaux violet et indigo : la brume) et .parallax-fg (60 px, rgba(15,15,26,.95) vers transparent : le sol). Sous le défileur, l'indice .slr-scroll-hint « Scrollez pour le parallax » (11,2 px, blanc à 40 %, bottom: 8px du cadre) rebondit de 4 px toutes les 2 s. Le champ JavaScript est vide.
Le moteur tient en deux propriétés. scroll-timeline: --parallaxScroll y sur le défileur déclare une timeline nommée qui suit sa position verticale ; chaque plan y attache son animation par animation-timeline: --parallaxScroll, avec animation-duration: auto, animation-timing-function: linear, animation-fill-mode: both et animation-range: normal : la progression vaut scrollTop ÷ 1400. Quatre @keyframes, tous en translateY : parallaxStars 20 → −20 px (étoiles et lune), parallaxSlow 40 → −40 px (crêtes), parallaxMed 80 → −80 px (brume), parallaxFast 120 → −30 px (sol). Plus le plan est proche, plus il court : 40, 80, 160 et 150 px sur la même course, soit 1 px pour 35 px défilés au fond et 1 px pour 8,75 à la brume. Mesuré dans Chromium 151 et WebKit 26.5, page vierge, valeurs identiques : à 140 px de défilement (10 %), 16 / 32 / 64 / 105 px ; à 700 px (50 %), 0 / 0 / 0 / 45 ; à 1 400 px, −20 / −40 / −80 / −30. Deux copies collées dans la même page donnent deux défileurs et deux timelines indépendantes (mesuré : chacune poussée à 700 px, chacune à 0) — pas d'id, rien à renommer.
Au repos, la scène est enfoncée : les bases des crêtes sont 40 px sous le bord bas, la brume et le sol sont entièrement hors cadre, la lune est à 40 px du haut. En défilant, tout remonte à des vitesses différentes ; à mi-course les crêtes touchent le bord et le sol montre ses 15 premiers pixels ; en fin de course les crêtes flottent 40 px au-dessus du bord, le sol occupe la bande 208–268 px du viewport et laisse sous lui 30 px de fond de cadre (sa dernière image-clé est −30, pas 0), la lune touche le bord haut. Le viewport est transparent : le ciel est le fond de .demo-preview. Deux règles tiennent l'ensemble. La hauteur fixe du défileur : en height: 100% sous un parent sans hauteur définie, il retombe à la hauteur de son contenu, la course vaut 0 et rien ne bouge (mesuré dans les trois moteurs). Et l'overflow: hidden du viewport, qui coupe les crêtes débordantes et le sol enfoncé de 120 px au repos — sans lui, le viewport gagnerait sa propre barre de défilement.
Accessibilité
- prefers-reduced-motion absent du code : mesuré sous émulation, les plans suivent toujours le défilement (0 / 0 / 0 / 45 px à mi-course, comme sans préférence) et l'indice rebondit toujours. Rien n'est caché pour autant : le parallaxe n'avance que par le geste du lecteur, seul le rebond tourne en boucle. Ajoutez
@media (prefers-reduced-motion: reduce) { .slr-scroll-hint { animation: none } }; pour figer aussi les plans, reprenez dans cette media query la liste de sélecteurs du repli@supports: la scène reste à plat, complète. - Clavier : mesuré, Tab donne le focus au défileur sans
tabindexdans Chromium 151 et Firefox 153 (activeElement=.parallax-container) : flèche bas avance de 40 px (51 dans Firefox), Page suivante de 285 (303), Fin va au bout, 1 400. WebKit 26.5 ne focalise pas la zone : le focus reste surbody, les flèches ne font rien. Ajouteztabindex="0", unaria-labelet un style:focus-visible. Au doigt, le geste doit commencer dans la zone ;overscroll-behavior: containévite d'entraîner la page en bout de course. - Contraste : le seul texte est l'indice, 11,2 px en blanc à 40 % sur
#0a0a0f— rendurgb(108,108,111), 3,8:1, sous le seuil de 4,5:1 des petits corps ; il est écrit en français en dur. Passez-le à 60 % (rgba(255,255,255,.6)), traduisez-le ou retirez lespan— la@keyframes hintBouncepart avec lui. Tout texte posé sur la scène doit tenir son contraste sur le ciel et sur les crêtes, plus claires. - Lecteurs d'écran et repli : quinze
divetspanvides plus une phrase française — rien à lire. Posezaria-hidden="true"sur.parallax-viewport(ourole="img"et unaria-labelsur le défileur si la scène illustre quelque chose) et gardez le contenu utile hors de la scène : un lecteur d'écran ne défile pas pour faire apparaître un sol. Sans animations pilotées par le défilement, le repli@supportsmontre la scène complète et immobile ; sans CSS du tout, il ne reste que l'indice.
Compatibilité navigateur
CSS seul : scroll-timeline (timeline nommée), animation-timeline, animation-range, animation-duration: auto, position: sticky, overflow: hidden auto, dégradés, triangles de bordure, cinq @keyframes. Zéro dépendance, zéro JavaScript. Les animations pilotées par le défilement existent dans Chrome et Edge 115+, Safari et iOS 26+ (mesuré dans WebKit 26.5 : mêmes valeurs que Chromium 151 à chaque position). Firefox : aucune version. Mesuré dans Firefox 153 : CSS.supports('animation-timeline: scroll()') répond faux et animation-duration: auto est calculée 0s. Le repli @supports not (animation-timeline: scroll()) du code vendu met animation: none sur les cinq plans : chacun reste à sa place de repos (transform: none mesuré à 0, 350, 700, 1 050 et 1 400 px de défilement) — étoiles et lune en haut, crêtes et brume posées sur le bord bas, sol collé au bord. Le défileur défile normalement sur 1 400 px, le viewport reste épinglé, l'indice rebondit : un visiteur Firefox voit une scène de nuit fixe et complète, que le défilement ne fait pas bouger. Sans ce repli, il verrait les images-clés finales : plans remontés de 20 à 80 px et bande vide de 30 px sous le sol (mesuré).
Le repli ne cache rien : il annule les cinq animations et la scène s'affiche à plat, complète — la composition de mi-course, sol compris. Si le mouvement est le message, masquez l'invitation dans le même bloc : .slr-scroll-hint { display: none }. Pour un parallaxe réel partout, il faut un écouteur scroll qui écrit les transform, comme le fait Parallax Layers (fx-0576).
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :
<div class="demo-preview">
<div class="parallax-container">
<div class="parallax-scene">
<div class="parallax-viewport">
<div class="parallax-stars slr-parallax-layer">
<span class="p-star"></span><span class="p-star"></span><span class="p-star"></span><span class="p-star"></span>
<span class="p-star"></span><span class="p-star"></span><span class="p-star"></span><span class="p-star"></span>
</div>
<div class="parallax-moon"></div>
<div class="slr-parallax-bg slr-parallax-layer"></div>
<div class="parallax-mid slr-parallax-layer"></div>
<div class="parallax-fg slr-parallax-layer"></div>
</div>
</div>
</div>
<span class="slr-scroll-hint">…</span>
</div>
Le code complet HTML + CSS + JS de Parallax Layers, 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éfaut | Effet |
|---|---|---|
Amplitudes des plans (CSS — @keyframes parallaxStars / parallaxSlow / parallaxMed / parallaxFast) |
20 → −20, 40 → −40, 80 → −80, 120 → −30 px | Des pixels fixes quelle que soit la course : sur 1 400 px, 40 px valent 1 px pour 35 défilés ; sur 400 px, 1 pour 10. Gardez le plan le plus proche le plus rapide, c'est ce qui fait la profondeur. Terminez parallaxFast à translateY(0) pour que le sol reste collé au bord en fin de course. |
Course (CSS — .parallax-scene { height: 600% }) |
1 680 px de piste, 1 400 px de course | Course = hauteur de la piste − hauteur du défileur ; les amplitudes s'y étalent. 300% donne 560 px et un parallaxe 2,5 fois plus vif ; height: auto avec du contenu placé après le viewport (remonté d'une marge négative égale à sa hauteur) fait défiler ce contenu par-dessus la scène, comme dans les trois scènes ci-dessus. |
Hauteur du cadre (CSS — .parallax-container et .parallax-viewport { height: 280px }) |
280 px, les deux | Changez les deux ensemble : le viewport épinglé doit faire la hauteur du défileur. Une valeur fixe est obligatoire sur le défileur (en height: 100% sous un parent sans hauteur : course 0, mesuré). Plans ancrés en bas et étoiles en pourcentage : la scène se redistribue seule. |
Ciel et couleurs des plans (CSS — .demo-preview { background }, .slr-parallax-bg, .parallax-mid::before, .parallax-fg) |
ciel #0a0a0f, indigo rgba(99,102,241,.15–.25), violet rgba(139,92,246,.2–.3), sol rgba(15,15,26,.95) | Le viewport est transparent : le ciel est le fond du cadre. Les plans sont des dégradés translucides : sur un ciel clair, montez leurs opacités (.4 à .6) ou passez à des couleurs pleines. Le sol, opaque à 95 %, sert aussi de fond à ce que vous posez en bas du cadre. |
Crêtes (CSS — .slr-parallax-bg::before et ::after) |
280 × 140 px à left: −10 % ; 240 × 110 px à right: −5 % | Des triangles de bordure : la largeur vaut border-left + border-right, la hauteur border-bottom. 200 px de bordures font une crête de 400 × 200 px ; left: 30% la déplace. Une troisième crête demande un élément de plus dans la bande. |
Étoiles et lune (HTML — huit .p-star ; CSS — .p-star:nth-child(n), .parallax-moon) |
8 points de 2 px (deux de 3 px), opacités .3 à .8 ; lune 30 px à top 20 / right 30, halo 20 px | Ajoutez des span et leur règle :nth-child (position en %, opacité) ; sans règle, un point tombe en haut à gauche. La lune partage parallaxStars avec les étoiles ; donnez-lui parallaxSlow pour la rapprocher, ou aucune animation pour la fixer. |
Indice « Scrollez pour le parallax » (HTML + CSS — .slr-scroll-hint, @keyframes hintBounce) |
8 px du bas du cadre, 11,2 px, blanc à 40 %, rebond 4 px / 2 s | Ancré sur .demo-preview (position: relative) : sans ce cadre, il tombe au bas de la page. Texte français en dur, 3,8:1 de contraste : traduisez, éclaircissez ou supprimez le span. C'est le seul mouvement autonome de l'effet. |
Repli sans animation-timeline (CSS — @supports not (animation-timeline: scroll())) |
animation: none sur les cinq plans | Firefox et les navigateurs anciens voient la scène à plat. Pour leur montrer autre chose, remplacez le bloc : un transform: translateY(…) fixe par plan compose la vue de votre choix. |
FAQ
height: 100% sous un parent sans hauteur définie, il retombe à la hauteur de son contenu, la course vaut 0 et la timeline n'a rien à suivre. Le défileur lui-même : la timeline est nommée sur .parallax-container, c'est lui qu'il faut faire défiler, pas la page ; la molette ne l'atteint que si le pointeur est dessus, et un overflow: visible posé par votre CSS le rend inerte. Pour piloter la scène par le défilement de la page, remplacez la timeline nommée par animation-timeline: scroll(root) sur les cinq plans, retirez l'overflow du conteneur et gardez le viewport sticky dans une section assez haute.parallaxFast va de 120 à −30 px sur une bande de 60 px ancrée en bas. Au repos, la bande est 120 px sous le bord : invisible. Elle affleure à 700 px de course (15 px visibles), est entière à 1 050 px, puis monte jusqu'à −30 : ses 60 px occupent la bande 208–268 d'un viewport de 280 et les 30 px du bas montrent le fond du cadre — mesuré identique à 390 et 1 280 px de large. C'est le dessin vendu : les plans s'enfoncent puis s'élèvent, et la composition « assemblée » est celle de mi-course, la même que le repli Firefox. Pour un sol collé au bord jusqu'au bout, terminez parallaxFast à translateY(0) ; pour cacher l'écart sans toucher aux amplitudes, donnez au sol 90 px de haut (.parallax-fg { height: 90px }) : à −30 il couvre encore le bord.scroll et six écritures de style par événement sur des formes abstraites (halo, trois formes tournées de 180°, mot PARALLAXE grossi et fondu), avec quatre const globales qui limitent la page à une instance ; en échange, il tourne dans Firefox. fx-0573 n'a pas une ligne de script : une timeline nommée, quatre @keyframes, un viewport sticky qui ne sort jamais du cadre, autant d'instances que voulu (mesuré : deux copies, deux timelines indépendantes) — et rien ne bouge dans Firefox. Sa scène est un paysage dessiné en CSS, pas des formes à remplacer. fx-0592, comme Parallax Layers CSS (fx-0548), est aussi en CSS pur mais avec animation-timeline: scroll() anonyme et des calques qui défilent avec leur section : la scène monte et sort du cadre. fx-0573 est le seul des trois où le cadre reste épinglé pendant que les plans glissent dedans.