Pulse Ring
Deux anneaux de 50 px s'élargissent de 25 à 75 px en 2 s ease-out, s'effacent et repartent — ::after décalé d'une demi-période. Pur CSS, aucun script.
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
L'effet repose sur deux pseudo-éléments (::before et ::after) du conteneur .loader-pulse (50 × 50 px, position: relative). Chacun est positionné en absolu sur inset: 0 — il occupe le même carré 50 × 50 px que le conteneur — avec border: 3px solid #6366f1 et border-radius: 50%, ce qui en fait un anneau. Aucun enfant HTML n'est nécessaire ; aucun JavaScript n'est chargé.
L'animation @keyframes pulse fait passer la transform de scale(.5) à scale(1.5) et l'opacity de 1 à 0, en 2 s ease-out, en boucle infinie. Le diamètre visible de l'anneau part de 25 px (50 × 0,5) et atteint 75 px (50 × 1,5) ; comme scale() s'applique aussi au trait, l'épaisseur apparente passe de 1,5 px au départ à 4,5 px à l'arrivée — l'anneau s'épaissit légèrement en s'élargissant. La courbe ease-out produit une expansion rapide dès le début qui ralentit vers la fin : l'anneau jaillit du centre puis flotte avant de s'effacer. ::after reçoit animation-delay: 1s, soit la demi-période exacte : à tout instant, un anneau naît tandis que l'autre s'efface — un nouveau départ par seconde, deux cycles alternés sans interruption.
Le code ne contient aucune référence à var(--…) (vérifié : zéro occurrence) ni aucun script. La propriété inset requiert Chrome 87+, Firefox 87+ ou Safari 14.1+. Le nom @keyframes pulse n'est pas préfixé : si la page de l'acheteur définit déjà une animation portant ce nom, l'anneau adoptera celle de la page — renommez l'animation si ce risque existe. Le HTML vendu contient la div.demo-preview du site ; l'acheteur n'a besoin que de <div class="loader-pulse"></div> et du CSS sans ce wrapper.
Accessibilité
- prefers-reduced-motion absent du code — mesuré sous Playwright :
animationPlayState: "running"avecprefers-reduced-motion: reduceémulé (Chromium). Les deux anneaux s'animent quelle que soit la préférence OS. Correctif : ajouter@media (prefers-reduced-motion: reduce) { .loader-pulse::before, .loader-pulse::after { animation: none; } }. - Aucun attribut d'accessibilité : ni
role="status", niaria-busy, niaria-live, ni texte alternatif. Les lecteurs d'écran ne signalent pas le chargement. Pour un indicateur fonctionnel, ajouterrole="status"sur.loader-pulseet un<span class="sr-only">Chargement…</span>à l'intérieur (masqué visuellement, visible des technologies d'assistance). - L'animation est exclusivement visuelle et ne transmet aucune information par la couleur seule : l'anneau est soit visible soit absent. Si l'état de chargement doit être communiqué, il faut un message textuel associé — l'effet seul ne suffit pas.
- Le nom
@keyframes pulsen'est pas préfixé : en cas de collision sur la page hôte, l'anneau peut adopter une animation étrangère et le comportement visuel n'est plus garanti. Renommer enloader-pulse-animou similaire si plusieurs animations « pulse » coexistent.
Compatibilité navigateur
CSS pur : nécessite @keyframes, transform: scale(), opacity, inset et border-radius: 50%. Aucune dépendance JS.
Sans inset (Chrome < 87, Safari < 14.1) : les pseudo-éléments ne se positionnent plus dans le conteneur — remplacer par top: 0; right: 0; bottom: 0; left: 0 pour couvrir les navigateurs plus anciens. Sans animations CSS, les deux pseudo-éléments restent figés à scale(.5) — deux petits arcs statiques, ni erreur ni page cassée.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="loader-pulse"></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 — width / height de .loader-pulse) |
50 × 50 px | Diamètre de départ (× 0,5) et d'arrivée (× 1,5) des anneaux. 24 px = indicateur bouton ; 80–100 px = centrage plein écran. |
Couleur (CSS — border: 3px solid #6366f1) |
#6366f1 (indigo) | Couleur des deux anneaux. Changer la valeur hex suffit ; rgba permet d'ajuster l'opacité initiale indépendamment de l'animation. |
Épaisseur du trait (CSS — border: 3px solid …) |
3 px | Épaisseur nominale ; scale() la multiplie : visuellement 1,5 px au départ, 4,5 px à l'arrivée. Passer à 5 px pour des anneaux plus affirmés sur de grands formats. |
Durée d'un cycle (CSS — animation: 2s …) |
2 s | Durée d'un aller complet scale(0,5) → scale(1,5). 1 s = pulsation rapide ; 3–4 s = respiration lente. Si vous changez cette valeur, ajustez le délai du second anneau à la moitié. |
Décalage du second anneau (CSS — animation-delay: 1s sur ::after) |
1 s (demi-période) | Déphasage entre les deux anneaux. À la demi-période, les cycles alternent parfaitement — un départ par seconde. 0,5 s (quart de période) : les deux anneaux se chevauchent davantage, effet de « double battement ». |
Échelle de départ (CSS — scale(.5) dans @keyframes pulse) |
0,5 — anneau à 25 px de diamètre sur un conteneur de 50 px | scale(0) : l'anneau naît d'un point (effet onde de choc). scale(0,8) : l'expansion est courte et subtile, déjà presque au centre. |
Courbe de timing (CSS — ease-out) |
ease-out | Expansion rapide au départ, ralentissement en fin. linear : expansion mécanique régulière. ease-in-out : départ et fin doux, mouvement plus symétrique — proche d'un sonar. |
FAQ
requestAnimationFrame, calcule un intervalle de battement simulé (500 + Math.sin(time × 0,001) × 100 ms, soit 1,7 à 2,5 pulsations par seconde), applique une interpolation linéaire sur un conteneur de 120 px et partage sa boucle rAF avec d'autres visualiseurs de la même IIFE. fx-0423 est un indicateur de chargement : 2 pseudo-éléments CSS, aucun JavaScript, durée fixe de 2 s ease-out, déphasage exact d'une demi-période. Les deux effets sont sans rapport fonctionnel.scale(0), l'anneau partirait d'un point géométrique — un effet « onde de choc » ou « goutte d'eau ». À scale(0,5), il commence déjà à 25 px de diamètre : le regard perçoit un anneau qui s'élargit et s'estompe, pas un cercle qui naît. Cela rend la pulsation plus douce et plus lisible à petite taille (24 px de conteneur). Pour l'effet « onde de choc », remplacer scale(.5) par scale(0) — le trait visuel sera alors 0 px au départ et 4,5 px à l'arrivée..loader-pulse { --pr-dur: 2s; } et remplacer les valeurs dans animation: var(--pr-dur) ease-out … et dans animation-delay: calc(var(--pr-dur) / 2). Les deux anneaux restent automatiquement à la demi-période quelle que soit la durée, et plusieurs instances peuvent coexister avec des vitesses différentes en surchargeant --pr-dur sur chaque conteneur.