Recursive Circles
Un cercle SVG qui contient trois cercles, qui en contiennent chacun trois, sur quatre niveaux ; une respiration descend du plus grand aux plus petits.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. SVG comprend 30 effets, dont 3 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
La figure est construite par une fonction récursive, grow(). Elle trace un cercle, puis place à l'intérieur data-branches cercles enfants (3 par défaut) tangents entre eux et au bord du parent. Leur rayon vient d'une formule exacte : r × sin(π/n) / (1 + sin(π/n)), soit 46 % du parent pour trois enfants, 50 % pour deux. La fonction s'appelle ensuite sur chaque enfant, en tournant d'un demi-pas à chaque niveau, jusqu'à data-depth (4 par défaut). Total : 1 + 3 + 9 + 27 + 81 = 121 cercles.
Le dessin se fait dans un repère fixe, viewBox="-112 -112 224 224", centré sur 0 : la figure est toujours au milieu de la zone et s'adapte à sa plus petite dimension, sans calcul de position. Chaque niveau a sa couleur (indigo, violet, magenta, cyan, vert, puis on recommence) et son épaisseur de trait, un peu plus fine à chaque génération (calculée en CSS à partir du niveau) et toujours mesurée en pixels d'écran grâce à vector-effect: non-scaling-stroke.
L'animation rccBreath fait passer chaque cercle de 95 % à 100 % de sa taille et de 45 % à 100 % d'opacité en 3 secondes. Le niveau sert de retard : 0,25 s de plus par génération, donc la vague part du grand cercle et descend vers les plus petits. Les délais sont négatifs (- 100 × durée) : rien ne saute au chargement. Un MutationObserver surveille data-depth, data-branches et data-colors : changer l'un de ces attributs redessine la figure, sans autre appel.
Accessibilité
- Figure décorative : le SVG porte
aria-hidden="true". Si la figure illustre une donnée (comme le nombre de membres d'un réseau), écrivez cette donnée en texte à côté. - Mouvement réduit : sous
prefers-reduced-motion: reduce, l'animation est retirée ; tous les cercles restent à pleine taille et pleine opacité, la figure complète reste lisible. - Rien à activer : aucun élément focusable, la figure ne réagit ni à la souris ni au toucher. Les changements de profondeur passent par l'attribut, que votre propre contrôle (curseur, boutons) peut piloter.
- Grande profondeur : au-delà de 5 niveaux avec 3 branches, les derniers cercles font moins d'un pixel dans une zone de 300 px. Ils n'apportent rien à la lecture et alourdissent la page.
Compatibilité navigateur
SVG, transform-box: fill-box (Chrome 64, Firefox 55, Safari 11) et max() pour l'épaisseur du trait (Chrome 79, Firefox 75, Safari 11.1), versions relevées dans les données MDN. Mesuré dans Chromium 151, Firefox 153 et WebKit 26.5 : 121 cercles par copie, centre de la figure au centre exact de la zone, deux copies indépendantes.
Sans JavaScript, le SVG reste vide. Dans un navigateur sans max(), le trait garde l'épaisseur par défaut du SVG (1 px) et la figure reste juste.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0611-root" data-depth="4" data-branches="3">
<svg class="rcc-svg" viewBox="-112 -112 224 224" aria-hidden="true"></svg>
</div>
Paiement unique, sans abonnement — le code est à toi pour toujours
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
data-depth (racine) |
4 | Nombre de générations sous le premier cercle (0 à 6). Modifiable à tout moment : la figure se redessine. |
data-branches (racine) |
3 | Enfants par cercle (2 à 8). 2 donne des paires qui alternent horizontal et vertical, 4 une rosace en croix, 6 une couronne. |
data-colors (racine) |
#6366f1, #8b5cf6, #d946ef, #06b6d4, #22c55e | Couleurs des niveaux, séparées par des virgules ; la liste recommence si la profondeur la dépasse. |
--rcc-stroke |
1.5px | Épaisseur du trait du premier cercle ; chaque niveau en perd 15 %, sans descendre sous 0,6 px. |
--rcc-speed |
3s | Durée d'une respiration complète. |
--rcc-step |
0.25s | Retard d'un niveau sur le précédent. 0 fait respirer toute la figure ensemble. |
--rcc-height / --rcc-bg |
300px / #0a0a0f | Hauteur et fond de la zone. La figure prend la plus petite des deux dimensions, centrée. |
FAQ
data-depth="1" puis "2" pour voir chaque génération reproduire la précédente à l'intérieur de chaque cercle.root.setAttribute('data-depth', 3). L'effet observe cet attribut et redessine aussitôt. La même chose vaut pour data-branches et data-colors.