Orbit
Un satellite de 12 px tourne autour d'un centre fixe de 8 px en 1 s exactement — rayon mesuré de 19 px, deux pseudo-éléments, zéro JavaScript.
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. Chargement comprend 29 effets, dont 4 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
Le conteneur .loader-orbit est un carré de 50 × 50 px en position: relative. Deux pseudo-éléments, aucun DOM ajouté. ::after : disque de 8 × 8 px, couleur #d946ef, centré par left: 50%; top: 50%; transform: translate(-50%, -50%) — il ne bouge jamais. ::before : disque de 12 × 12 px, couleur #6366f1, ancré en left: 50%; top: 0, avec transform-origin: 50% 25px.
La valeur transform-origin: 50% 25px place le pivot à (6 px, 25 px) dans le repère local du ::before : 6 px est la moitié de 12 px (centre horizontal du disque), 25 px est la moitié de 50 px (milieu exact du conteneur en Y). La keyframe unique to { transform: translateX(-50%) rotate(360deg) } combine deux effets simultanés : translateX(-50%) décale le centre d'orbite de 6 px vers la gauche, ramenant le pivot de (31 px, 25 px) à (25 px, 25 px) — le centre géométrique du conteneur ; rotate(360deg) fait pivoter le disque autour de ce point. Rayon résultant : 25 − 6 = 19 px, mesuré constant sur 8 échantillons successifs espacés de 125 ms.
L'animation 1s linear infinite donne 360 °/s constant, sens horaire. Aucun JavaScript, aucune variable CSS, aucun élément créé au chargement. La valeur implicite du keyframe from est le transform: translateX(-50%) déclaré dans le CSS de l'élément, ce qui assure une transition sans rupture entre la position de départ (disque au sommet, centré) et la boucle continue.
Accessibilité
- prefers-reduced-motion absent du code : l'animation tourne en permanence quelle que soit la préférence système. Mesuré sous
reducedMotion: reduceen Playwright : la composante sinus du transform passe de 0,5430 à −0,5450 en 500 ms — l'orbite ne ralentit pas. Ajoutez@media (prefers-reduced-motion: reduce) { .loader-orbit::before { animation: none } }pour stopper la rotation et laisser le satellite immobile en position de départ. - Pour un indicateur de chargement, aucune sémantique n'est fournie : le
.loader-orbitest undivvide sansrole, sansaria-busy, sansaria-labelet sansaria-live. Les lecteurs d'écran ignorent les deux pseudo-éléments (contenu CSS). Ajoutez au minimumrole="status"etaria-label="Chargement en cours"; si ce loader remplace un contenu dynamique, enveloppez-le dans une régionaria-live="polite". - L'effet fonctionne pleinement sur mobile (CSS Animations ne requiert pas d'interaction tactile) : le satellite orbite dès le chargement sans geste préalable. Aucun curseur personnalisé, aucun événement souris — intégrable tel quel dans un contexte tactile.
- Contraste : les deux disques sont des indicateurs d'état, pas du texte (seuil WCAG 3:1 pour les composants UI).
#6366f1sur#0a0a0f: 4,4:1 ✓.#d946efsur#0a0a0f: 5,3:1 ✓. Sur fond clair, les deux couleurs chutent sous 3:1 — remplacez#6366f1par#4338caet#d946efpar#a21cafpour tenir le seuil sur blanc.
Compatibilité navigateur
CSS pur : @keyframes, transform avec translateX() et rotate(), transform-origin, border-radius: 50%, pseudo-éléments ::before/::after. Aucune dépendance.
Sans CSS Animations (IE 9 et antérieurs), le ::before s'affiche à l'état initial — disque #6366f1 immobile en haut du conteneur, centré horizontalement. Le ::after reste centré. Aucun JavaScript à charger, aucune erreur console.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="loader-orbit"></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 |
|---|---|---|
Taille du conteneur (CSS — .loader-orbit { width: 50px; height: 50px }) |
50 × 50 px | Redimensionne tout le système. Après un changement, recalculez le transform-origin du satellite : sa valeur Y doit rester égale à la moitié de la nouvelle hauteur pour que le pivot reste au centre. Les tailles des deux disques sont indépendantes et se règlent séparément. |
Rayon d'orbite (CSS — ::before { transform-origin: 50% 25px }) |
25 px → rayon effectif 19 px | La valeur Y du transform-origin est le bras de rotation ; le rayon effectif vaut bras − demi-hauteur du satellite (25 − 6 = 19 px). Réduire à 20px donne un rayon de 14 px (orbite serrée) ; augmenter à 30px donne 24 px (adapter le conteneur à ≥ 62 × 62 px en conséquence). |
Taille du satellite (CSS — ::before { width: 12px; height: 12px }) |
12 × 12 px | Ajustez aussi transform-origin X : 50 % de la nouvelle largeur (ex. 8px → transform-origin: 4px 25px). Sans cet ajustement, le satellite orbite légèrement décalé du centre. |
Couleur du satellite (CSS — ::before { background: #6366f1 }) |
#6366f1 (indigo) | Indépendante du centre. Toute couleur CSS est acceptée : dégradé (background: linear-gradient(...)), semi-transparent, blanc. Pas de border ni de box-shadow dans le code vendu — à ajouter si un halo est souhaité. |
Couleur du centre (CSS — ::after { background: #d946ef }) |
#d946ef (rose/magenta) | Peut aussi être transparent pour supprimer le point central et ne laisser que le satellite tournant, ou background: none; border: 2px solid #d946ef; border-radius: 50% pour un anneau creux. |
Durée (CSS — animation: 1s linear) |
1 s — 360 °/s | 0.5s : orbite rapide, indique une activité intense. 2s : orbite lente, convient aux états d'attente prolongée ou aux contextes éditoriaux. La valeur linear maintient la vitesse angulaire constante ; ease-in-out produirait une accélération/décélération perceptible à chaque passage au sommet. |
Taille du centre (CSS — ::after { width: 8px; height: 8px }) |
8 × 8 px | Aucune incidence sur la trajectoire du satellite. Un centre de 0 px (display: none) donne un effet de comète solitaire. Un centre de 20 px (occupant 40 % du conteneur) renforce la métaphore planète/lune. |
FAQ
transform-origin et la moitié de la hauteur du satellite. La formule est : rayon = transform-origin-Y − (satellite-height / 2). Pour un conteneur de 60 × 60 px avec un satellite de 14 px, posez transform-origin: 7px 30px (30 = 60/2, 7 = 14/2) : rayon = 30 − 7 = 23 px. Ne changez jamais l'une sans recalculer les autres, sinon le pivot dérive du centre.conic-gradient qui tourne — un seul corps, métaphore « arc de cercle progressif ». Orbit propose deux corps distincts : un centre fixe et un satellite en mouvement — métaphore planétaire, lisible même à 24 px, sans épaisseur de bordure ni dégradé. Choisissez Orbit quand le design demande un système plutôt qu'un cercle..loader-orbit) avec un transform-origin et une durée différents. Le code vendu ne contient qu'un satellite (le ::before) ; ajouter un second div enfant en position: absolute avec ses propres pseudo-éléments ou sa propre animation de rotation est la voie la plus propre — pas de modification du code existant.