Pulse Loading
Sept os — avatar 48 px, bandeau 120 px, trois lignes — pulsent en opacité (1 → 0,4 → 1) en 1,5 s ease-in-out ; décalages 0–400 ms. CSS pur, 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 HTML vendu contient un conteneur .pulse-skel (280 px de large, 296 px de haut, background: rgba(255,255,255,.03), bordure rgba(255,255,255,.06), border-radius: 16px, padding: 20px) avec sept os. L'en-tête (.pulse-skel-header, flex, gap 14 px) aligne le cercle .pulse-skel-avatar (48×48 px) et une colonne flex‑1 contenant .pulse-skel-title (14 px de haut, 65 % de la largeur interne) et .pulse-skel-subtitle (10 px, 45 %). En dessous : .pulse-skel-img (100 % × 120 px, border-radius 10 px) puis trois .pulse-skel-line (10 px de haut : les deux premières à 100 %, la dernière à 55 %). Tous les os partagent background: rgba(255,255,255,.08) et border-radius: 6px (50 % pour le cercle). Le conteneur .demo-preview présent dans le HTML vendu est le cadre de démonstration du site — il n'est pas à inclure dans une intégration.
Un seul @keyframes pulseBreath — 0 % et 100 % à opacity: 1, 50 % à opacity: 0,4 — s'applique à tous les os : durée 1,5 s, ease-in-out, infini. Les décalages échelonnent le départ : avatar et titre à 0 s, bandeau image à 0,1 s, sous-titre à 0,15 s, puis les trois lignes à 0,2 s / 0,3 s / 0,4 s. L'écart total de 400 ms entre le premier et le dernier os produit une vague descendante de brillance : à t = 750 ms (fond du cycle à 1,5 s), l'image est à opacity ≈ 0,40 tandis que la troisième ligne vient d'atteindre son plein éclat. Aucun JavaScript — le champ js du JSON vendu est vide.
Contrairement aux variantes shimmer de la catégorie — fx-0439 Card Skeleton, fx-0446 Wave Shimmer, fx-0447 Rainbow Shimmer — qui animent la position d'un dégradé sur un pseudo-élément ::after, Pulse Loading n'anime que l'opacité du fond de chaque os : aucun pseudo-élément, aucun dégradé, une seule animation. Un défaut CSS affecte la largeur des lignes : le sélecteur .pulse-skel-line:nth-child(2) ne matche aucun élément — les lignes occupent les positions 3, 4 et 5 parmi les enfants directs de .pulse-skel, pas la position 2 (occupée par .pulse-skel-img). La deuxième ligne s'affiche à 100 % au lieu des 90 % prévus ; la cascade prévue 100 %/90 %/55 % devient 100 %/100 %/55 %, effaçant la décroissance médiane.
Accessibilité
- prefers-reduced-motion absent du code :
pulseBreaths'exécute sans condition, quelle que soit la préférence de l'utilisateur. Ajoutez@media (prefers-reduced-motion: reduce) { .pulse-bone, .pulse-bone-circle { animation: none; opacity: 1; } }pour figer les os au repos. - Le conteneur
.pulse-skeln'a nirole="status", niaria-busy="true", ni texte alternatif : les lecteurs d'écran ne perçoivent qu'une zone vide silencieuse. Ajoutezrole="status" aria-label="Chargement en cours"sur.pulse-skelet retirez-les quand le contenu réel apparaît. - Les sept os sont des
divvides sans attribut. Posezaria-hidden="true"sur.pulse-skel(ou sur chaque os) pour éviter une liste de nœuds muets dans l'arbre d'accessibilité — l'information de chargement est alors portée uniquement par le texte alternatif du conteneur. - En thème clair, le fond d'os
rgba(255,255,255,.08)sur fond blanc devient invisible. Prévoyez une variable CSS — par exemple--pulse-bone-bg— et adaptez sa valeur selon le thème ;rgba(0,0,0,.07)est un bon point de départ pour les fonds clairs.
Compatibilité navigateur
CSS pur (aucun JavaScript) : requiert @keyframes et animation (IE 10+), flex (IE 11 partiel), border-radius et rgba(). Aucun pseudo-élément, aucun dégradé, aucune transformation.
Sans CSS animation (IE 9), les sept os s'affichent à opacity: 1 et ne pulsent plus — le squelette reste visible et statique, ce qui reste un repli cohérent pour un indicateur de chargement.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="pulse-skel">
<div class="pulse-skel-header">
<div class="pulse-bone-circle pulse-skel-avatar"></div>
<div style="flex:1">
<div class="pulse-bone pulse-skel-title"></div>
<div class="pulse-bone pulse-skel-subtitle"></div>
</div>
</div>
<div class="pulse-bone pulse-skel-img"></div>
<div class="pulse-bone pulse-skel-line"></div>
<!-- 2 autres .pulse-skel-line -->
</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 |
|---|---|---|
Couleur des os (CSS — .pulse-bone, .pulse-bone-circle { background }) |
rgba(255, 255, 255, .08) | Luminosité du fond de chaque os au plein éclat. rgba(255,255,255,.12) pour un contraste plus marqué sur fond très sombre ; rgba(0,0,0,.07) pour un thème clair. |
Opacité minimale (CSS keyframe — 50% { opacity: .4 }) |
0,4 | Profondeur du « souffle » : 0 = disparition totale à mi-cycle (clignotement), 0,7 = variation à peine perceptible. Entre 0,3 et 0,5, l'effet ressemble à une respiration ; en dessous de 0,2, il se lit comme un clignotement. |
Durée du cycle (CSS — animation: 1.5s …) |
1,5 s | Vitesse de la respiration. 0,8 s = rapide, sentiment d'urgence ; 2,5 s = lent et doux, adapté aux interfaces de bien-être. Changez la valeur en même temps dans le sélecteur générique et les surcharges de délai. |
Décalage maximal (CSS — dernière surcharge animation-delay: .4s) |
400 ms (troisième ligne) | Amplitude de la vague : 0 ms = tous les os pulsent simultanément ; 800 ms = vague très marquée mais le dernier os est visiblement en retard sur le premier. Redistribuez les délais intermédiaires proportionnellement. |
Largeur de la carte (CSS — .pulse-skel { width: 280px }) |
280 px | Largeur du conteneur. Passez à 100% pour une carte fluide dans une grille ; les os en pourcentage (width: 65%) s'adaptent automatiquement. |
Hauteur du bandeau image (CSS — .pulse-skel-img { height: 120px }) |
120 px | Zone de prévisualisation d'image. 60 px pour un widget de graphique ; 200 px pour un contenu image-first ; supprimez l'élément HTML si votre interface n'a pas de bandeau. |
Correction de la deuxième ligne (CSS — .pulse-skel-line:nth-child(2)) |
90 % — inactif (selector broken) | Le sélecteur actuel ne matche aucun élément : remplacez-le par .pulse-skel > .pulse-skel-line:nth-child(4) (4e enfant de .pulse-skel, soit la 2e ligne) pour retrouver la cascade 100 %/90 %/55 %. |
FAQ
::after : une lumière balaie l'os horizontalement. Pulse Loading anime uniquement l'opacité du fond de l'os lui-même : pas de pseudo-élément, pas de dégradé, pas de mouvement horizontal. Résultat : moins de couches de rendu, code plus court, et un rendu qui ne crée pas de reflet directionnel — adapté aux interfaces où le shimmer mobile paraîtrait trop actif (mode nuit, écrans OLED où les pixels noirs sont éteints)..pulse-skel-line:nth-child(2) cible un élément qui est à la fois .pulse-skel-line et le deuxième enfant de son parent. Dans la structure du code vendu, le deuxième enfant direct de .pulse-skel est .pulse-skel-img, pas une ligne : les lignes sont aux positions 3, 4 et 5. Le sélecteur ne matche donc rien et la règle width: 90% n'est jamais appliquée. Correctif : .pulse-skel > .pulse-skel-line:nth-child(4) { width: 90% }..pulse-skel autant de fois que nécessaire et appliquez un décalage de base croissant à chaque carte via une propriété personnalisée. Exemple : .pulse-skel:nth-child(2) { --card-offset: 200ms }, puis sur chaque os animation-delay: calc(var(--delay-bone, 0s) + var(--card-offset, 0s)). La carte 2 démarre 200 ms après la carte 1, produisant une vague entre les cartes en plus de la vague interne à chaque carte.