Snow Fall
Cent flocons blancs tombent sur un canvas 2D — taille, vitesse et opacité aléatoires, oscillation sinusoïdale horizontale, boucle RAF continue.
Vous aurez accès à la démo interactive avec un compte gratuit.
Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Atmosphère comprend 57 effets, dont 10 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
setupCanvas() lit les dimensions du parent et redimensionne le canvas en conséquence. À l'initialisation, 100 particules sont créées avec des valeurs aléatoires indépendantes : position (x, y) répartie sur toute la surface, rayon r entre 1 et 4 px, vitesse verticale speed entre 0,5 et 1,5 px/frame, drift horizontal constant wind dans ±0,25 px/frame, et opacité entre 0,3 et 0,8. Ces valeurs ne changent pas pendant la vie d'un flocon.
La boucle requestAnimationFrame efface le canvas et redessine le fond #0a0a0f à chaque frame. Pour chaque flocon : y += speed (chute verticale) et x += wind + 0,3 × sin(0,01 × y) — l'oscillation sinusoïdale est basée sur la position Y, non sur le temps : deux flocons à la même hauteur oscilleront en phase. Les flocons sont des arc() pleins dessinés en rgba(255,255,255, opacity).
Le wrapping aux bords est simple et non interpolé : un flocon qui sort par le bas réapparaît en haut (y = −5) à une abscisse aléatoire ; ceux qui franchissent le bord gauche ou droit sautent sur le côté opposé. Le pool de 100 flocons est constant, aucune particule n'est créée ou détruite.
L'effet n'intègre ni IntersectionObserver (le RAF tourne même hors viewport), ni ResizeObserver (le canvas n'est pas recalibré si le conteneur change de taille), ni API publique. Toutes les constantes sont hardcodées dans l'IIFE.
Accessibilité
- prefers-reduced-motion absent : le code ne vérifie pas la préférence OS. L'animation tourne toujours, quelle que soit la configuration utilisateur. À corriger manuellement si le contexte l'exige : entourer la boucle RAF d'un test
window.matchMedia('(prefers-reduced-motion:reduce)').matches. - Le canvas n'a pas d'
aria-hiddendans le HTML source — ajouteraria-hidden="true"pour éviter que les lecteurs d'écran tentent d'explorer un canvas non textuel. - Pas de
role="img"niaria-labelsur le conteneur : si l'effet est décoratif, masquer le canvas aux technologies d'assistance ; si informatif, ajouter un label sur l'élément parent. - Les flocons blancs
rgba(255,255,255,…)sur fond#0a0a0f(quasi-noir) affichent un rapport de contraste > 18:1 — aucun problème de lisibilité pour les flocons eux-mêmes. - L'effet est purement décoratif et n'expose aucune interaction au clavier ni à la souris — aucun focus natif à gérer.
Compatibilité navigateur
Nécessite Canvas 2D Context et requestAnimationFrame — supportés dans tous les navigateurs modernes depuis 2013.
Si <code>getElementById('psSnow')</code> retourne <code>null</code> (élément absent ou ID modifié), <code>setupCanvas()</code> retourne <code>null</code> et l'IIFE s'arrête silencieusement — aucune erreur JS, le conteneur s'affiche avec son fond CSS.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="demo-preview">
<!-- Wrapper positionné — remplacez width/height par les dimensions de votre conteneur -->
<div class="ps-canvas-wrap" role="img" aria-label="Flocons de neige tombant en animation">
<canvas class="ps-canvas" id="psSnow" aria-hidden="true"></canvas>
</div>
</div>
HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
| count (JS : `a < 100`) | 100 | Nombre de flocons actifs. 60 pour un fond léger, 150 pour une tempête dense. Au-delà de 200, surveiller les performances sur mobile bas de gamme. |
| rayon (JS : `3 * Math.random() + 1`) | 1–4 px | Plage de rayon des flocons. Modifier min et amplitude : `1.5 * Math.random() + 0.5` pour des flocons plus fins ; `5 * Math.random() + 2` pour des flocons larges. |
| speed (JS : `1 * Math.random() + .5`) | 0.5–1.5 px/frame | Vitesse de chute verticale. `0.3 * Math.random() + 0.2` pour une bruine lente ; `2 * Math.random() + 1` pour une tempête. |
| wind (JS : `.5 * Math.random() - .25`) | ±0.25 px/frame | Drift horizontal constant par flocon. `1 * Math.random() - 0.5` pour un vent latéral marqué ; `0` pour une chute purement verticale. |
| opacité (JS : `.5 * Math.random() + .3`) | 0.3–0.8 | Plage d'opacité des flocons. `0.15 * Math.random() + 0.05` pour une neige quasi-transparente (effet givrage de vitre). |
| amplitude oscillation (JS : `0.3 * Math.sin`) | 0.3 | Amplitude du balancement sinusoïdal horizontal. 0 = chute droite sans oscillation ; 0,8 = effet blizzard tourbillonnant. |
| fréquence oscillation (JS : `0.01 * n.y`) | 0.01 | Fréquence du cycle sinusoïdal en fonction de Y. 0,03 raccourcit le cycle (vibrements rapides) ; 0,005 l'allonge (ondulation lente et ample). |
FAQ
#0a0a0f à chaque frame via ctx.fillRect(0, 0, w, h). Pour une neige transparente sur fond personnalisé, supprimez les deux lignes fillStyle = '#0a0a0f' et fillRect(...) du JS, rendez le canvas position: absolute avec background: transparent et placez votre fond en CSS derrière le canvas.IntersectionObserver pour la couper quand le canvas est hors du viewport.rgba(255,255,255, opacity). Remplacez 255,255,255 par les valeurs RVB souhaitées — par exemple 173,216,230 pour du bleu glace ou 255,220,180 pour des pétales de cerisier. Pour plusieurs couleurs, définissez un tableau de couleurs et piocheez-en une aléatoirement à l'initialisation de chaque flocon.