Color Shift
Un fond de section (.sdc-color-bg, absolu, inset 0) dont le dégradé à 135° passe par cinq palettes — nuit, indigo, violet, rose, orange — sur une course de 520 px, en CSS seul : animation-timeline: scroll() lit la boîte de 280 px, zéro JavaScript. Mesuré : la palette bascule d'un coup, sans fondu, à 66, 196, 326 et 456 px dans Chromium.
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 empile cinq boîtes : le cadre .demo-preview (flex centré, min-height: 300px, position: relative, fond #0a0a0f, texte blanc), la boîte défilante .sdc-scroll-container (100% × 280px, overflow-y: auto, scroll-behavior: smooth, barre de 4 px en ::-webkit-scrollbar), le plateau .sdc-color-content (800px, colonne flex, position: relative) et, dedans, côte à côte, le fond .sdc-color-bg (position: absolute; inset: 0, vide) puis la section .sdc-color-section (flex: 1, flex centré) qui porte .sdc-color-text : un h3 de 24 px graisse 800 et un p de 12 px en blanc à 60 %, en z-index: 1 au-dessus du fond. La course vaut 800 − 280 = 520 px. Le champ JS est vide ; aucune variable du site, aucun fichier hébergé, aucune erreur console : 2,4 Ko de CSS.
Le fond n'a aucun background propre : il est entièrement fourni par @keyframes sdcColorShift, cinq étapes qui posent chacune un linear-gradient(135deg, …) à deux couleurs — #1e1b4b → #0f172a (0 %), #4c1d95 → #1e1b4b (25 %), #7c3aed → #4c1d95 (50 %), #ec4899 → #7c3aed (75 %), #f97316 → #ec4899 (100 %) — et lues par animation-timeline: scroll() : sans argument, la timeline est celle du conteneur défilant le plus proche, ici .sdc-scroll-container ; animation-duration: auto et animation-range: normal étalent les 100 % sur toute la course. Mesuré dans Chromium 151, molette par crans de 104 px : progression 0 → .2 → .4 → .6 → .8 → 1, et le fond garde la dernière palette en butée (état finished ; rien ne disparaît malgré animation-fill-mode: none). Mais un dégradé ne s'interpole pas : entre deux étapes, le navigateur ne fond pas les couleurs, il bascule. Chromium change de palette à mi-chemin de chaque segment — au pixel : 66, 196, 326 et 456 px — et WebKit 26.5 dès le premier pixel du segment — 1, 131, 261 et 391 px —, si bien que la palette « nuit » n'y existe qu'à scrollTop = 0. Cinq couleurs, quatre coupures nettes ; pour un vrai fondu, c'est une couleur qu'il faut animer, pas un dégradé (voir la FAQ).
Le fond est un frère de la section, pas son enfant : son inset: 0 se mesure sur le premier ancêtre positionné. C'est la ligne position: relative de .sdc-color-content qui lui fait couvrir les 800 px du plateau ; sans elle (mesuré en la retirant), l'ancêtre positionné devient la boîte de 280 px, le fond ne fait plus que 280 px, défile avec le contenu et sort du cadre — à 260 px il n'en reste qu'une bande de 20 px, à 326 px plus rien, et les palettes rose et orange ne sont jamais vues. Le texte, lui, voyage avec le plateau : centré à 400 px, il est hors cadre au repos (375–425 px pour une fenêtre de 280), entre par le bas à 96 px, sort par le haut à 425 px — visible sur 329 des 520 px de course, sous les palettes indigo, violet et rose. Au repos, le visiteur voit donc une boîte « nuit » vide ; le titre n'apparaît qu'en défilant. Deux copies collées dans la même page donnent deux boîtes indépendantes, chacune lisant son propre conteneur ; la police du h3 vient d'un style en ligne (Inter n'est pas chargée, le navigateur passe à la police système).
Accessibilité
- prefers-reduced-motion absent du code : mesuré sous émulation, les palettes basculent aux mêmes pixels et l'indice pulse toujours (
sdcHintPulse running). Le changement de fond est piloté par le geste du lecteur — rien ne bouge sans lui —, ce qui le range dans les animations déclenchées par l'interaction (WCAG 2.3.3). Ajoutez@media (prefers-reduced-motion: reduce) { .sdc-scroll-hint { animation: none } .sdc-scroll-container { scroll-behavior: auto } }; si les coupures nettes vous gênent pour un lecteur sensible, figez une palette :.sdc-color-bg { animation: none; background: linear-gradient(135deg, #1e1b4b, #0f172a) }. - Contraste (calculé sur les deux couleurs de chaque palette) : le titre blanc de 24 px graisse 800 (seuil 3:1) tient sur nuit (16:1), indigo (11:1), violet (5,7:1) et rose (3,5:1), mais tombe à 2,8:1 sur l'orange
#f97316. Le paragraphe de 12 px en blanc à 60 % (seuil 4,5:1) ne tient que sur nuit (6,5:1) et indigo (4,9:1) : 3,0:1 sur le violet, 2,1:1 sur le rose, 1,9:1 sur l'orange. Pour un texte lu sur toute la course, gardez#fffà 100 % et assombrissez les deux dernières palettes, ou posez le texte sur une carte translucide (scène de la tour). - Clavier : mesuré, Chromium et Firefox donnent le focus à la boîte par Tab sans
tabindex(flèche bas : 40 px dans Chromium, 51 px dans Firefox ; Fin : 520 px) ; WebKit non — le focus reste surbodyet les flèches ne font rien. Ajouteztabindex="0", unaria-labelet un style:focus-visiblesur.sdc-scroll-container. Molette et doigt sont natifs (aucun écouteur) ;overscroll-behavior: containévite d'entraîner la page en butée. - Lecteurs d'écran et sens de la couleur : la palette n'est pas annoncée et ne doit porter aucune information seule — l'heure, l'étage ou le mois qu'elle illustre doivent être écrits dans le contenu (WCAG 1.4.1).
.sdc-color-bgest undivvide : posezaria-hidden="true"dessus, ainsi que sur l'indice « Scrollez ↓ » (français en dur ; blanc à 30 % dont l'opacité pulse de .3 à .7, les deux se multiplient : 1,2:1 au creux de sa pulsation, 1,8:1 au sommet). Leh3vendu doit suivre le niveau de titre courant de votre page. Sans CSS, tout se lit dans l'ordre du document.
Compatibilité navigateur
CSS seul : animation-timeline: scroll(), animation-duration: auto, animation-range, inset, @keyframes sur background, flexbox, scroll-behavior, ::-webkit-scrollbar (Blink et WebKit seulement). Zéro JavaScript, zéro dépendance. Les animations pilotées par le défilement existent dans Chrome et Edge depuis la version 115, dans Safari et iOS depuis la 26 ; Firefox ne les lit dans aucune version (mesuré dans Firefox 153 : CSS.supports('animation-timeline: scroll()') renvoie false, animation-duration: auto est rejeté et retombe à 0s). Le code vendu ne contient pas de repli @supports.
Firefox, mesuré : le fond calcule background-image: none, la boîte est plate, de la couleur du cadre (#0a0a0f) ; le titre blanc et le paragraphe restent lisibles à leur passage, l'indice pulse, rien n'est caché, aucune erreur console — mais aucune couleur ne change. Pour donner à ces visiteurs la palette de départ, trois lignes à coller sous le code : @supports not (animation-timeline: scroll()) { .sdc-color-bg { background: linear-gradient(135deg, #1e1b4b, #0f172a) } }. Avant Chrome 115 et Safari 26, même rendu que Firefox. Sans JavaScript : rien à perdre, il n'y en a pas.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :
<div class="demo-preview">
<div class="sdc-scroll-container">
<div class="sdc-color-content">
<div class="sdc-color-bg"></div>
<div class="sdc-color-section">
<div class="sdc-color-text">
<h3>…</h3>
<p>…</p>
</div>
</div>
</div>
</div>
<span class="sdc-scroll-hint">…</span>
</div>
Le code complet HTML + CSS + JS de Color Shift, 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 |
|---|---|---|
Palettes (CSS — @keyframes sdcColorShift) |
5 étapes : #1e1b4b→#0f172a, #4c1d95→#1e1b4b, #7c3aed→#4c1d95, #ec4899→#7c3aed, #f97316→#ec4899 | Chaque étape est un dégradé complet à deux couleurs : remplacez-les par les vôtres en gardant la forme. Le nombre d'étapes fixe le nombre de coupures — quatre étapes, trois bascules, à 1/6, 3/6 et 5/6 de la course dans Chromium. Une couleur unie par étape (background: #1e1b4b) se comporte pareil : par bascule, sans fondu. |
Course (CSS — .sdc-color-content { height: 800px }, .sdc-scroll-container { height: 280px }) |
520 px (bascules à 66, 196, 326 et 456 px) | La timeline couvre exactement plateau − boîte. Votre contenu remplace les 800 px (height: auto) et les bascules se replacent seules à 12,5 / 37,5 / 62,5 / 87,5 % de la nouvelle course ; une boîte plus haute (60vh) n'a rien d'autre à changer. |
Défileur (CSS — animation-timeline: scroll()) |
scroll() = conteneur défilant le plus proche | scroll(root) lit le défilement de la page : le fond suit alors toute la page, sans boîte (retirez overflow-y, posez le fond en position: fixed; inset: 0 derrière le contenu). Une timeline nommée — scroll-timeline: --fond y sur le défileur, animation-timeline: --fond sur le fond — pilote un fond placé hors du défileur. |
Fenêtre de course (CSS — animation-range: normal) |
normal (0 → 100 %) | animation-range: 0 60% épuise les cinq palettes aux trois cinquièmes de la course puis garde l'orange ; 20% 100% laisse la nuit sur le premier cinquième. Les bascules se resserrent d'autant. |
Angle du dégradé (CSS — 135deg dans chaque étape) |
135° (haut gauche → bas droite) | Le dégradé est tracé sur les 800 px du plateau, pas sur la fenêtre de 280 : la boîte n'en montre qu'une tranche, presque unie, qui glisse avec le défilement. 90deg le rend horizontal et visible en entier à toute position. |
Texte (CSS — .sdc-color-text ; h3 1,5 rem graisse 800, p .75 rem à 60 %) |
centré à 400 px, visible de 96 à 424 px | Le bloc voyage avec le plateau. Pour un titre visible dès le repos, passez-le en position: sticky; top: 0 dans la section, ou remplissez toute la hauteur (listes, paragraphes) : le fond couvre tout le plateau. |
Habillage de la boîte (CSS — scroll-behavior: smooth, ::-webkit-scrollbar 4 px, .sdc-scroll-hint) |
smooth / barre de 4 px violette / « Scrollez ↓ » pulsant 2 s | smooth ne lisse que les défilements programmés ; la barre stylée n'existe que dans Blink et WebKit (Firefox garde la sienne). L'indice est un reste du catalogue : français en dur, accroché à .demo-preview — supprimez le span, la @keyframes sdcHintPulse part avec lui. |
FAQ
background avec des linear-gradient(), et qu'un dégradé n'est pas interpolable : la spécification le traite comme une valeur discrète, le navigateur affiche l'une ou l'autre étape, jamais un mélange. Mesuré dans Chromium 151 : la bascule se fait à mi-segment (66, 196, 326, 456 px pour 520 de course) ; dans WebKit 26.5, dès le premier pixel du segment (1, 131, 261, 391 px). Pour un vrai fondu, animez des couleurs, pas des images : déclarez deux propriétés enregistrées — @property --c1 { syntax: '<color>'; inherits: false; initial-value: #1e1b4b }, idem --c2 —, écrivez background: linear-gradient(135deg, var(--c1), var(--c2)) sur .sdc-color-bg et faites varier --c1 et --c2 dans les étapes : un <color> enregistré s'interpole, le dégradé glisse alors en continu (Chrome 85+, Safari 16.4+)..sdc-color-bg et tout votre contenu soit positionné et fasse toute la hauteur défilable. Le fond est en position: absolute; inset: 0 : il prend les dimensions du premier ancêtre positionné. Dans le code vendu, c'est .sdc-color-content (position: relative, 800 px). Si votre section n'a pas de position, l'ancêtre positionné devient la boîte défilante elle-même (.sdc-scroll-container est en position: relative) : le fond ne mesure plus que sa hauteur visible, 280 px, part avec le contenu et sort par le haut — mesuré : bande de 20 px à 260 px de défilement, plus rien à partir de 326, les deux dernières palettes jamais affichées. Une ligne suffit : position: relative sur le parent direct du fond.animation-timeline: scroll(), mais pas la même propriété ni la même surface. fx-0554 anime background-color d'un carré de 180 px — #6366f1 → #d946ef → #06b6d4 → #10b981, quatre étapes — et la couleur d'une légende : une couleur s'interpole, donc elle glisse en continu (mesuré : rgb(133, 93, 240) à 50 px, rgb(168, 83, 240) à 100 px), mais autour du carré, le fond reste noir. fx-0559 anime background du fond entier avec cinq dégradés : toute la section change d'ambiance, par bascules nettes. fx-0585 Sticky Image Change est plus proche sur la mécanique — quatre linear-gradient(135deg, …) tenus par paliers (0–20, 25–45, 50–70, 75–100 %) sur animation-timeline: scroll(nearest), donc les mêmes bascules nettes — mais pas sur la surface ni sur la structure : ce qui change de couleur est un bandeau de 120 px en position: sticky; top: 10px, qui reste en vue et signale par sa teinte la section en cours de lecture, pendant que quatre panneaux de texte se révèlent chacun à leur entrée par animation-timeline: view() (animation-range: entry 0% entry 50%) ; le fond de la boîte, lui, reste sombre (#0a0a0f). fx-0559 n'a ni sticky ni panneaux : un seul fond absolu sous toute la section, et rien d'autre ne bouge. Prenez fx-0554 pour teinter un objet posé dans un texte, fx-0585 pour un repère épinglé qui accompagne des panneaux, fx-0559 pour changer l'atmosphère d'une section entière.