Classic Spinner
Div 50 × 50 px, radius 50 %, bordure 4 px : côté haut #6366f1 opaque, trois côtés à 20 % — @keyframes spin 1 s linéaire, aucun pseudo-élément, aucun JS.
Cet effet est gratuit — la catégorie Chargement en contient 29 au total, dont 4 gratuits. Effect.Labs regroupe 811 effets vanilla. Découvrir la catégorie →
Exemples d'usage
Envoi vers Imprimante bureau…
Rapport-septembre.pdf · 3 pages · Recto verso
Vérification en deux étapes
Code envoyé par SMS au 06 •• •• •• 47
Comment ça marche
L'effet est un seul <div class="loader-spinner"> sans enfant ni pseudo-élément. border-radius: 50% sur un carré de 50 × 50 px (zone de contenu, box-sizing: content-box par défaut) trace le cercle ; la bordure de 4 px porte les couleurs. Le boîtier rendu total fait donc 58 × 58 px (50 + 2 × 4). Aucune image, aucun SVG, aucun script exécuté.
L'arc visible émerge de la répartition des opacités sur les quatre côtés. La règle border-color: rgb(99, 102, 241) rgba(99, 102, 241, 0.2) rgba(99, 102, 241, 0.2) utilise la forme à trois valeurs du raccourci (haut / droite+gauche / bas) : le côté haut est pleinement opaque, les trois autres partagent la même teinte à 20 %. L'arc n'est pas découpé ni masqué — seule la différence d'opacité le révèle. La propriété border-image: none est posée explicitement pour neutraliser toute cascade héritée.
@keyframes spin ne contient qu'un seul arrêt : 100% { transform: rotate(360deg) }. L'arrêt 0 % est implicite — le navigateur part de la valeur calculée de l'élément au repos, soit l'identité (rotate(0deg)). La déclaration complète animation: 1s linear 0s infinite normal none running spin fixe : durée 1 s, progression linéaire, délai zéro, boucle infinie. Une révolution par seconde, sans accélération. La clé js du fichier est un commentaire (// Effet CSS pur — pas de JavaScript nécessaire) : rien ne s'exécute.
Accessibilité
- prefers-reduced-motion absent (mesuré) : sous émulation
@media (prefers-reduced-motion: reduce),animationPlayStateresterunning— la rotation continue à pleine vitesse. Ajouter@media (prefers-reduced-motion: reduce) { .loader-spinner { animation-duration: 8s; } }pour ralentir, ouanimation: nonesi un cercle statique suffit à indiquer l'attente. - Aucun attribut ARIA (mesuré) :
role,aria-label,aria-liveetaria-busysont tous absents — un lecteur d'écran ignore complètement l'élément. Pour un indicateur de chargement, ajouterrole='status' aria-live='polite'et un libellé masqué :<span class='sr-only'>Chargement en cours…</span>à l'intérieur du div. - Contraste : l'arc opaque
#6366f1sur fond#0a0a0fdonne un rapport de 5,1:1 (WCAG 1.4.11 seuil 3:1, conforme). Sur fond blanc : 4,5:1, conforme également. La partie à 20 % est décorative — aucun critère de contraste ne s'y applique. - Pointer events : aucune règle
pointer-events: nonen'est posée. Si le spinner est superposé à du contenu interactif dans un overlay de chargement bloquant, ajouterpointer-events: nonesur le spinner oucursor: waitsur le conteneur parent.
Compatibilité navigateur
CSS pur : border-radius, border-color avec rgba, @keyframes, animation, transform: rotate(). Aucune variable CSS du design system, aucun JS, aucune dépendance.
Sur IE 10, @keyframes et animation nécessitent le préfixe -ms- — sans lui, le div s'affiche comme un cercle statique de 58 px avec l'arc coloré. Sur IE 9 et antérieurs, même résultat statique. La page reste fonctionnelle dans les deux cas.
Le code
Copiez les trois blocs dans votre page. Aucune dépendance.
<div class="loader-spinner">
</div>
.loader-spinner {
width: 50px;
height: 50px;
border-width: 4px;
border-style: solid;
border-color: rgb(99, 102, 241) rgba(99, 102, 241, 0.2) rgba(99, 102, 241, 0.2);
border-image: none;
border-radius: 50%;
animation: 1s linear 0s infinite normal none running spin;
}
@keyframes spin {
100% {
transform: rotate(360deg);
}
}
// Effet CSS pur — pas de JavaScript nécessaire
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
Dimensions (CSS — width et height) |
50px | Zone de contenu ; boîtier rendu = valeur + 2 × border-width. À 20 px avec bordure 2 px : boîtier total 24 px. |
Épaisseur de l'arc (CSS — border-width) |
4px | Conserver un rapport ≈ 8 % de la taille : 30 px → 2–3 px, 80 px → 6–7 px. Trop fine : arc invisible ; trop épaisse : la surface opaque occupe plus d'un quart du cercle et l'arc disparaît dans une masse. |
Couleur de l'arc (CSS — premier terme de border-color) |
rgb(99, 102, 241) | Teinte du côté haut (l'arc visible). Les trois autres côtés utilisent la même teinte réduite à 20 % — changer ce premier terme modifie les quatre côtés à la fois. |
Opacité de l'anneau fantôme (CSS — valeur alpha dans rgba) |
0.2 | 0 = trois côtés invisibles, l'arc tourne sur fond nu. 0.5 = anneau bien visible, contraste plus marqué. 1 = disque plein tournant sans arc apparent. |
Durée d'une révolution (CSS — 1s dans animation) |
1s | 0.6 s : rapide, sensation d'urgence. 1.5 s : lent, connoté « traitement long ». Descendre sous 0.4 s : l'arc paraît instable. |
Fonction de progression (CSS — linear dans animation) |
linear | ease-in-out crée une illusion de décélération à chaque début de tour ; la rotation paraît vivante mais moins mécanique. linear est le choix standard pour un spinner. |
box-sizing (CSS — absent, hérité content-box) |
content-box (hérité) | Ajouter box-sizing: border-box : width: 50px englobe alors la bordure, boîtier rendu = 50 px au lieu de 58 px. Utile pour s'insérer dans un conteneur à largeur fixe. |
FAQ
Pourquoi trois valeurs dans border-color plutôt que quatre ?
La propriété border-color avec trois valeurs suit la règle haut / droite+gauche / bas : la deuxième valeur s'applique simultanément aux côtés droit et gauche. Quatre valeurs (rgb(99,102,241) rgba(…) rgba(…) rgba(…)) donneraient le même rendu ; trois termes économisent une répétition. Le côté haut reste seul opaque, les trois autres à 20 %.
Quelle différence avec Gradient Ring (fx-0435) qui trace lui aussi un arc tournant ?
Gradient Ring produit son arc par conic-gradient(transparent, #6366f1) sur le fond du div et creuse le centre via un ::before. L'arc y est dégradé — il s'efface progressivement du transparent vers l'opaque. Classic Spinner n'a aucun pseudo-élément et produit un arc à bord franc par border-color. Si votre composant utilise déjà ::before et ::after pour une icône ou un badge, Classic Spinner s'intègre sans conflit.
Le spinner s'affiche écrasé ou trop grand dans mon composant.
La cause la plus fréquente est l'héritage de box-sizing: border-box d'un framework CSS parent — le boîtier passe de 58 px à 50 px (le cercle reste rond, seulement plus petit). Si le spinner est enfant direct d'un display: flex avec align-items: stretch, il peut s'étirer ; ajouter flex-shrink: 0; align-self: center preserve ses dimensions. Isoler le spinner dans un conteneur neutre (display: flex; align-items: center; justify-content: center) neutralise les deux cas.