Aller au contenu
BDU Cauri, accueilv0.1.0
Composants

Spinners

Les spinners indiquent qu’une opération est en cours quand sa durée est inconnue : connexion, chargement d’un relevé, envoi d’un virement. Ils sont écrits en CSS pur, sans image.

Spinner circulaire#

.spinner-border dessine un cercle qui tourne. Ajoutez toujours un texte masqué pour les lecteurs d’écran, avec role="status" sur le spinner.

Chargement…
<div class="spinner-border" role="status">
  <span class="visually-hidden">Chargement…</span>
</div>

Spinner pulsant#

.spinner-grow dessine un disque qui grossit et s’estompe, pour un rendu plus discret.

Chargement…
<div class="spinner-grow" role="status">
  <span class="visually-hidden">Chargement…</span>
</div>

Couleurs#

Les spinners utilisent currentColor : changez leur couleur avec les classes de texte. Rappel : dans Cauri, text-secondary et text-success donnent le même vert.

Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
Chargement…
<div class="d-flex flex-wrap gap-3 mb-3">
  <div class="spinner-border text-primary" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-border text-success" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-border text-danger" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-border text-warning" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-border text-info" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-border text-body-secondary" role="status"><span class="visually-hidden">Chargement…</span></div>
</div>
<div class="d-flex flex-wrap gap-3">
  <div class="spinner-grow text-primary" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-grow text-success" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-grow text-danger" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-grow text-warning" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-grow text-info" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-grow text-body-secondary" role="status"><span class="visually-hidden">Chargement…</span></div>
</div>

Petite taille#

.spinner-border-sm et .spinner-grow-sm réduisent le spinner à 1 rem, par exemple pour l’intégrer dans un texte ou un bouton. Pour une taille libre, fixez width et height en ligne.

Chargement…
Chargement…
Chargement…
Chargement…
<div class="d-flex flex-wrap align-items-center gap-3">
  <div class="spinner-border spinner-border-sm" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-grow spinner-grow-sm" role="status"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-border" role="status" style="width: 3rem; height: 3rem;"><span class="visually-hidden">Chargement…</span></div>
  <div class="spinner-grow" role="status" style="width: 3rem; height: 3rem;"><span class="visually-hidden">Chargement…</span></div>
</div>

Alignement et espacement#

Les spinners sont des éléments en ligne : utilisez les utilitaires de flexbox, de texte ou de flottement pour les placer.

Chargement…
Chargement…
Chargement de votre relevé…
Chargement…
Vérification de votre identité
<div class="d-flex justify-content-center mb-3">
  <div class="spinner-border text-primary" role="status"><span class="visually-hidden">Chargement…</span></div>
</div>
<div class="text-center mb-3">
  <div class="spinner-border text-primary" role="status"><span class="visually-hidden">Chargement…</span></div>
</div>
<div class="d-flex align-items-center border rounded p-3 mb-3">
  <strong role="status">Chargement de votre relevé…</strong>
  <div class="spinner-border ms-auto" aria-hidden="true"></div>
</div>
<div class="clearfix border rounded p-3">
  <div class="spinner-border float-end" role="status"><span class="visually-hidden">Chargement…</span></div>
  Vérification de votre identité
</div>

Dans un bouton#

Ajoutez un petit spinner dans un bouton pour montrer qu’une action est en cours, et désactivez le bouton pour éviter un double envoi. Si le texte du bouton décrit déjà l’état, masquez le spinner avec aria-hidden="true".

<button class="btn btn-primary" type="button" disabled>
  <span class="spinner-border spinner-border-sm" aria-hidden="true"></span>
  <span class="visually-hidden" role="status">Envoi en cours…</span>
</button>
<button class="btn btn-primary" type="button" disabled>
  <span class="spinner-border spinner-border-sm" aria-hidden="true"></span>
  <span role="status">Virement en cours…</span>
</button>
<button class="btn btn-outline-primary" type="button" disabled>
  <span class="spinner-grow spinner-grow-sm" aria-hidden="true"></span>
  <span role="status">Chargement…</span>
</button>

Afficher un spinner pendant un chargement#

Le texte du bouton et son état disabled sont à rétablir quand l’opération est terminée, même en cas d’erreur.

const bouton = document.getElementById('bouton-virement');

async function envoyerVirement() {
  bouton.disabled = true;
  bouton.querySelector('.spinner-border').classList.remove('d-none');
  try {
    await fetch('/api/virements', { method: 'POST' });
  } finally {
    bouton.disabled = false;
    bouton.querySelector('.spinner-border').classList.add('d-none');
  }
}

Classes

Classes
ClasseRôle
.spinner-borderCercle qui tourne (2 rem, bordure de .25 em).
.spinner-growDisque qui grossit et s’estompe en boucle.
.spinner-border-sm, .spinner-grow-smPetite taille (1 rem).
.text-*Couleur du spinner (via currentColor).
.visually-hiddenTexte réservé aux lecteurs d’écran.

Variables Sass

Variables Sass
VariableValeur par défaut
$spinner-width2rem
$spinner-height$spinner-width
$spinner-vertical-align-.125em
$spinner-border-width.25em
$spinner-animation-speed.75s
$spinner-width-sm1rem
$spinner-height-sm$spinner-width-sm
$spinner-border-width-sm.2em

Personnalisation#

Les variables CSS --bs-spinner-* se règlent sur chaque spinner. Sous prefers-reduced-motion: reduce, la vitesse passe automatiquement à 1,5 s par tour.

// Sass : spinners plus grands et plus lents
$spinner-width: 2.5rem;
$spinner-animation-speed: 1s;

// CSS : un spinner précis
.spinner-releve {
  --bs-spinner-width: 3rem;
  --bs-spinner-height: 3rem;
  --bs-spinner-border-width: 0.3em;
  --bs-spinner-animation-speed: 1s;
}

Bonnes pratiques

À faire

  • Ajoutez un texte clair pour les lecteurs d’écran (« Chargement du relevé… »), dans un élément visually-hidden.
  • Placez role="status" sur le spinner ou sur son libellé pour que l’état soit annoncé poliment.
  • Affichez le spinner au plus près de la zone qui charge (dans le bouton, dans la carte).
  • Désactivez l’action qui vient d’être lancée pour éviter un double envoi.

À éviter

  • N’affichez pas un spinner pour une opération dont l’avancement est connu : utilisez une barre de progression.
  • Ne laissez pas un spinner tourner indéfiniment : prévoyez un message d’erreur et une possibilité de réessayer.
  • N’utilisez pas à la fois un spinner et un squelette de placeholders pour la même zone.

Accessibilité

  • Un spinner seul est ignoré des lecteurs d’écran : donnez-lui role="status" et un texte visually-hidden.
  • Si le texte visible décrit déjà l’état (« Virement en cours… »), marquez le spinner aria-hidden="true" pour éviter une annonce en double.
  • Quand l’utilisateur demande moins de mouvement (prefers-reduced-motion: reduce), la rotation et la pulsation ralentissent automatiquement.
  • La couleur par défaut suit celle du texte : vérifiez le contraste si vous la changez.
Charte provisoire, déduite du site public de la BDU CI. Elle sera remplacée par la charte officielle.