3D Bars
8 barres CSS en perspective 3D animées par synthèse sinusoïdale — rotateY oscillant par barre et double ombre portée décalée simulent le relief sans canvas.
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
Le conteneur .bars-3d active la scène 3D via perspective: 500px et transform-style: preserve-3d. Chaque barre reçoit un rotateX(-10deg) fixe — elle bascule légèrement vers le spectateur — et un rotateY dynamique centré sur −15°, ce qui expose la face latérale gauche et crée l'illusion d'un pavé en volume.
À chaque frame, getSimulatedAudio(8, time, baseFreq=2) génère 8 valeurs [0–1] par superposition de deux sinusoïdes dont la fréquence croît de +0,5 par index de barre, additionnées à 20 % de bruit aléatoire. La hauteur est mappée sur 20 + value × 80 px (fourchette 20 → 100 px). Les fréquences différentes par barre cassent la synchronie et donnent un mouvement organique.
La profondeur visuelle repose sur deux box-shadow solides (sans flou) : rgba(79,70,229,.5) 4px 4px 0 et rgba(79,70,229,.3) 8px 8px 0. Ces ombres décalées à droite et en bas simulent les faces latérale droite et le dessus des barres, là où un vrai modèle 3D nécessiterait de la géométrie supplémentaire.
L'oscillation de rotateY suit -15 + Math.sin(time × 0.002 + i × 0.5) × 5 degrés : le terme i × 0.5 introduit un déphasage par index, produisant une vague de rotation progressive de gauche à droite. Toutes les animations de la page partagent un unique requestAnimationFrame ; aucun IntersectionObserver n'est présent — la boucle tourne en permanence.
Accessibilité
- prefers-reduced-motion absent : le code ne teste pas ce média-query — la boucle RAF tourne indéfiniment quel que soit le réglage système. À implémenter avant tout déploiement accessible (ex. :
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;). - L'élément
.bars-3dne porte nirole, niaria-label, niaria-hidden. Pour un usage décoratif, ajoutezaria-hidden="true"sur le conteneur racine afin que les lecteurs d'écran ignorent les barres. - Aucun contrôle pause/stop n'est exposé — WCAG 2.2.2 (mécanisme de pause pour toute animation auto-lancée dépassant 5 s) n'est pas respecté en l'état.
- Les barres sont des
<div>non focusables et sans rôle sémantique : correct pour du décor pur, à compléter si l'effet porte de l'information réelle (ex. données de dashboard). - Contraste couleur : le dégradé indigo-violet sur fond
#0a0a0fdépasse le ratio 3:1 pour les éléments graphiques non textuels (WCAG 1.4.11 — conforme pour un élément décoratif).
Compatibilité navigateur
Nécessite CSS 3D transforms (perspective, transform-style, rotateX/Y) et requestAnimationFrame — disponibles depuis Chrome 36+, Firefox 16+, Safari 9+. Zéro dépendance externe.
Si JS est désactivé, les 8 barres s'affichent statiquement avec les transformations et hauteurs du HTML initial (styles inline) — l'effet visuel est préservé, figé. Aucune erreur JS fatale.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="demo-preview">
<div class="bars-3d" id="bars3d" aria-hidden="true">
<!-- 8 <div class="bar"> créés dynamiquement par le JS -->
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</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 |
|---|---|---|
| `.bars-3d .bar` — background | linear-gradient(135deg, #6366f1, #8b5cf6, #4f46e5) | Couleur et direction du dégradé des barres. Remplacez les trois hex par votre palette brand ; l'angle 135° oriente la lumière haut-gauche → bas-droit. |
| `.bars-3d` — perspective | 500px | Profondeur de la scène 3D CSS. 300 px = effet dramatique et exagéré ; 800–1000 px = inclinaison subtile, quasi-plate. |
`bars3dCount` (JS, ligne const bars3dCount = 8) |
8 | Nombre de barres créées dynamiquement. 4 barres = graphe épuré, 16 barres = visualiseur dense (pensez à réduire width et gap en conséquence). |
| `.bars-3d .bar` — width | 20px | Largeur de chaque barre. Combinez avec gap pour équilibrer l'espace négatif selon la largeur totale du conteneur. |
| `.bars-3d` — gap | 8px | Espacement entre barres. 4 px = aspect serré et dense, 14 px = aéré et minimaliste. |
`time × 0.002` dans rotateY (JS, animateBars3d) |
0.002 | Vitesse d'oscillation de la rotation par barre. 0.001 = vague lente, 0.004 = frémissement rapide. |
`20 + data[i] × 80` dans animateBars3d (JS) |
min 20 px, amplitude 80 px | Fourchette de hauteur. 10 + data[i] × 100 = barres rasantes à plein dynamisme ; 40 + data[i] × 40 = mouvement discret autour d'une mi-hauteur fixe. |
| `.bars-3d .bar` — box-shadow | rgba(79,70,229,.5) 4px 4px 0, rgba(79,70,229,.3) 8px 8px 0 | Ombres portées simulant les faces latérales du pavé 3D. Augmentez le décalage (6 px / 12 px) pour plus de profondeur, changez la couleur pour qu'elle reste cohérente avec le dégradé. |
FAQ
perspective, transform-style: preserve-3d et rotateX/rotateY sur des <div> ordinaires. La profondeur est renforcée par deux box-shadow décalés sans flou. Zéro canvas, zéro WebGL, zéro dépendance externe.getSimulatedAudio() par votre source réelle — par exemple un tableau issu de l'API Web Audio (analyser.getByteFrequencyData(buf)) ou un tableau de valeurs normalisées de votre propre API. La fonction animateBars3d n'attend qu'un tableau de valeurs entre 0 et 1 : ajustez height = 20 + data[i] * 80 en conséquence.IntersectionObserver dans l'implémentation actuelle. La boucle requestAnimationFrame tourne en permanence. Pour économiser le CPU hors du viewport, ajoutez un observer sur .bars-3d qui positionne un flag booléen paused et fait retourner animateBars3d immédiatement quand celui-ci est vrai.