Blur to Clear
Trois blocs dans une zone de 280 px : chacun passe de blur(10px) et opacité 0 à net et opaque entre son entrée dans le cadre et le milieu de celui-ci — animation-timeline: view(), animation-range: entry cover 50%. Ni scale ni translation, zéro JavaScript : la mise au point est le seul mouvement.
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
Quatre niveaux : le cadre .demo-preview (flex centré, min-height: 300px, position: relative, fond #0a0a0f, texte blanc), la zone défilante .sdc-scroll-container (100% × 280px, overflow-y: auto, scroll-behavior: smooth, barre WebKit de 4 px), le plateau .sb-blurtoclear-content (900 px fixes, padding: 60px 16px, colonne flex, gap: 30px) et trois .sb-blurtoclear-box : padding: 24px, rayon 16 px, dégradés à 135° cyan → violet, violet → rose, vert → cyan, un h4 de 1,1 rem graisse 800 (Inter en style en ligne, reste du catalogue) et un p de 0,75 rem en blanc à 90 %. Mesuré dans Chromium 151, page vierge : blocs de 91 px à 60, 181 et 302 px du haut du plateau, course 900 − 280 = 620 px. L'indice .sdc-scroll-hint « Scrollez ↓ » (absolu, 8 px du bas du cadre, 10,4 px, blanc à 30 %) pulse de .3 à .7 toutes les 2 s. Champ JavaScript vide, aucune variable du site, aucune erreur console, même rendu à 390 px et sur page blanche.
Chaque bloc part de filter: blur(10px); opacity: 0 ; une seule image-clé le ramène, @keyframes sbBlurClear { to { filter: blur(0); opacity: 1 } }. Le moteur n'est pas le temps mais la position : animation-timeline: view() attache la progression à la traversée du bloc dans le conteneur défilant le plus proche — la zone, pas la page — et animation-range: entry cover 50% borne la fenêtre utile : 0 % quand le bord haut du bloc franchit le bas de la zone (entry 0%), 100 % quand son centre atteint le centre de la zone, à 140 px (cover 50%). animation-duration: auto, linear et animation-fill-mode: both font le reste : progression proportionnelle, état de départ tenu avant la plage, état final tenu après. Pour 91 px dans 280, la plage mesure 185 px (demi-bloc + demi-zone), avec opacité = p et flou = 10 × (1 − p) : mesuré à la molette sur le troisième bloc, opacité .42 et blur(5.8px) à 100 px de défilement, .69 et 3,1 px à 150, net à 207.
La géométrie livrée ne traite pas les trois blocs pareil. Le premier (centre à 105 px) a déjà dépassé le milieu au repos : fill-mode: both le tient net avant tout défilement. Le deuxième est pris à mi-plage — mesuré au repos opacité .53, blur(4.7px), net dès 86 px. Seul le troisième joue la séquence entière, de 22 à 207 px. Ensuite plus rien sur les 413 px restants et, à partir de 393 px, la zone ne montre plus que son fond — 227 px de course vide, dus aux 900 px fixes du plateau. Aucun transform : un bloc ne bouge que parce que la zone défile, ce qui le distingue de Blur Reveal (fx-0543, scale(1.1) → 1) et de Zoom Into Content (fx-0570, scale(.3) → 1). Le filter animé pose chaque bloc sur sa propre couche de composition : trois blocs ne coûtent rien, cinquante se mesurent.
Accessibilité
- prefers-reduced-motion absent du code : mesuré sous émulation, rien ne change — troisième bloc à opacité 0 au repos, .42 à 100 px, indice qui pulse. L'animation est pilotée par le lecteur, sans déplacement ni zoom : cas bénin au regard de WCAG 2.3.3, mais un bloc invisible tant qu'on n'a pas défilé reste une gêne. Ajoutez
@media (prefers-reduced-motion: reduce) { .sb-blurtoclear-box { animation: none; filter: none; opacity: 1 } .sdc-scroll-hint { animation: none } }: tout est à plat et net, comme dans Firefox. - Clavier : mesuré, Tab donne le focus à la zone sans
tabindexdans Chromium (anneauoutline: auto) comme dans Firefox ; flèche bas avance de 40 px dans Chromium (troisième bloc à .10), de 51 px dans Firefox ; PageDown de 245 px (bloc net), Fin va à 620. Safari ne focalise pas une boîte défilante sanstabindex="0": ajoutez-le, avecrole="region", unaria-labelet un:focus-visiblevisible. - Contraste (titre 17,6 px graisse 800, sous le seuil « grand texte » de 18,66 px : 4,5:1 exigé) : blanc sur
#06b6d42,43:1,#8b5cf64,23:1,#ec48993,53:1,#10b9812,54:1 — aucune extrémité de dégradé ne passe ; le paragraphe de 12 px à 90 % va de 2,22 à 3,75:1. À mi-plage, texte et bloc à 50 % sur#0a0a0ftombent à 1,9-2,5:1, transitoire acceptable si l'état final est lisible : assombrissez les dégradés (#0e7490 → #6d28d9donne 5,4 et 7,1:1). L'indice à 30 % vaut 2,62:1 : décoratif,aria-hidden="true". - Lecteurs d'écran et repli : trois
divavech4etp, lus quelle que soit l'opacité —opacity: 0ne retire rien de l'arbre d'accessibilité, contrairement àvisibility: hidden. Leh4sans h2/h3 au-dessus casse le plan de la page. « Scrollez ↓ » est écrit en français en dur. Là oùanimation-timelinen'existe pas (Firefox, Safari avant 26), les blocs sont nets d'emblée : le contenu ne dépend jamais de l'effet.
Compatibilité navigateur
CSS seul, sans JavaScript ni dépendance : animation-timeline: view(), animation-range avec entry et cover, animation-duration: auto, filter: blur() animé. Chrome et Edge 115+, Safari et iOS 26+. Firefox : aucune version — mesuré dans Firefox 153, CSS.supports('animation-timeline: view()') répond faux, animation-duration: auto est rejeté et la durée retombe à 0 s : l'animation saute à son image-clé to, les trois blocs sont nets et opaques dès le chargement (opacité 1, blur(0) sur toute la course), la zone défile, rien n'est caché ni superposé. Pas de @supports dans le code, et pas besoin : l'état final est l'état lisible. Information d'achat : sur Firefox, votre visiteur voit une liste de cartes sans mise au point.
Sans animation-timeline (Firefox, Safari et iOS avant 26, Chrome et Edge avant 115), la déclaration est ignorée, animation-duration: auto aussi, et l'animation de 0 s se termine aussitôt : fill-mode: both applique l'image-clé finale, blocs nets et opaques, zone qui défile. Aucun script à activer.
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="sb-blurtoclear-content">
<div class="sb-blurtoclear-box">
<h4>…</h4>
<p>…</p>
</div>
<div class="sb-blurtoclear-box">…</div>
<div class="sb-blurtoclear-box">…</div>
</div>
</div>
<span class="sdc-scroll-hint">…</span>
</div>
Le code complet HTML + CSS + JS de Blur to Clear, 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 |
|---|---|---|
Plage de révélation (CSS — animation-range: entry cover 50%) |
entry 0% → cover 50% (185 px pour un bloc de 91 px dans 280) | entry 0% entry 100% : net dès que le bloc est entièrement entré (91 px de course). cover 20% cover 80% : mise au point étalée sur le gros de la traversée. entry 25% cover 50% : bloc invisible sur ses 23 premiers pixels. |
Flou de départ (CSS — filter: blur(10px)) |
10 px | 20 px (la valeur de fx-0543) efface la forme du bloc, 4 px donne un voile. Le flou couvre texte et fond : un texte de 12 px est illisible dès 3 px. |
Opacité de départ (CSS — opacity: 0) |
0 | À 0, un bloc hors plage est absent — d'où le troisième invisible au repos. .35 garde une silhouette floue qui annonce la suite ; l'image-clé mène toujours à 1. |
Courbe (CSS — animation-timing-function: linear) |
linear | Proportionnelle au défilement (mesuré : opacité .42 à 42 % de la plage). ease-out rend presque net dès le premier tiers, ease-in retarde la netteté jusqu'au centre. |
Hauteur de zone et longueur du plateau (CSS — .sdc-scroll-container { height: 280px }, .sb-blurtoclear-content { height: 900px }) |
280 px / 900 px (course 620, dont 227 px vides) | La plage d'un bloc vaut demi-bloc + demi-zone : une zone de 400 px porte chaque mise au point à 245 px. Plateau en height: auto pour que la course s'arrête au dernier bloc, plus un padding-bottom d'une demi-zone s'il doit atteindre le centre — le réglage des trois scènes. |
Blocs (CSS — .sb-blurtoclear-box, :nth-child(2), :nth-child(3)) |
padding 24 px, rayon 16 px, trois dégradés à 135° | Un quatrième bloc reprend le cyan → violet de la règle de base : ajoutez sa ligne :nth-child(4). Tout enfant est flouté avec le bloc, image comprise. |
Conteneur de la timeline (HTML/CSS — .sdc-scroll-container) |
zone de 280 px à overflow-y: auto |
view() choisit l'ancêtre défilant le plus proche. Sans la zone (ou avec overflow: visible; height: auto), la page pilote et chaque bloc devient net au milieu de la fenêtre. view(block 15%) resserre la plage de 15 % en haut et en bas. |
Indice « Scrollez ↓ » (HTML/CSS — .sdc-scroll-hint) |
8 px du bas du cadre, 10,4 px, blanc à 30 %, pulsation 2 s | Français en dur, positionné par rapport à .demo-preview : sans ce cadre, il tombe au bas de l'ancêtre positionné suivant. Supprimez le span et sdcHintPulse avec lui. |
FAQ
entry cover 50% est entièrement passée dès le chargement et fill-mode: both tient l'image-clé finale. Le deuxième va de −99 à 86 px : au repos il est à 53 %, mesuré opacité .53 et blur(4.7px). Seul le troisième (22 → 207 px) part de zéro. Pour que le premier joue aussi, poussez-le sous le bas de la zone (padding-top: 280px sur le plateau) ou raccourcissez la plage (entry 0% entry 100%, qui finit avant le centre). Dans les trois scènes de cette page, le premier bloc est volontairement net d'emblée : il montre l'état d'arrivée.animation-timeline: view(), zéro JavaScript), deux réglages qui changent tout. fx-0543 anime trois propriétés — opacity: 0 → 1, blur(20px) → 0, scale(1.1) → 1 — sur entry entry 60% : net quand 60 % de sa hauteur est entrée, 55 px de course pour 91 px, avant même d'être entièrement visible, et il rétrécit en s'affinant. fx-0551 n'anime que l'opacité et un flou de 10 px, sans transform, sur entry cover 50% : 185 px, 3,4 fois plus long, netteté au milieu de la zone. Prenez fx-0551 quand le contenu ne doit pas se déformer (photo produit, affiche, texte) ou quand la netteté doit coïncider avec la zone de lecture ; fx-0543 pour une entrée courte et théâtrale. Zoom Into Content (fx-0570) est le troisième réglage de la même technique : scale(.3) → 1 et blur(8px) sur la même plage, pour un bloc-héros. Sur Firefox, les trois se comportent pareil : contenu net d'emblée.view() se rattache au conteneur défilant le plus proche : sans .sdc-scroll-container, c'est la fenêtre qui pilote et cover 50% devient « centre du bloc au centre de l'écran » — sur un téléphone de 800 px de haut, la plage d'un bloc de 91 px fait 445 px. Le nombre de blocs est libre : la règle est une classe, chaque bloc porte sa timeline, seuls les fonds sont en :nth-child. Deux précautions : le dernier bloc n'atteint le centre que si la page peut encore défiler d'une demi-fenêtre sous lui (pied de page ou padding-bottom, sinon préférez entry 0% entry 100%) ; et chaque bloc flouté vit sur sa propre couche, léger pour une dizaine de cartes, à mesurer au-delà. view() lit l'axe vertical : rien ne réagit à un défilement horizontal.