Cartes✨ Premium

Bento with Stats

Grille bento de statistiques : les compteurs s'animent au défilement via IntersectionObserver, les barres de progression se révèlent au survol en transition CSS.

JSStatsCounter

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Cartes comprend 43 effets, dont 6 gratuits. Découvrir la catégorie →

3 exemples d'usage

Dashboard analytics — Métriques clés en un coup d'œil — Bento with Stats exemple 1

① Dashboard analytics — Métriques clés en un coup d'œil

QuandLa page d'accueil d'un outil d'analytics, de BI ou de monitoring s'ouvre et présente les KPIs principaux dans une grille bento compacte.
PourquoiL'animation des compteurs au scroll capte l'attention au moment où l'utilisateur arrive sur la zone de données — plus impactant qu'une liste de chiffres statiques.
RéglagesCibles : visites 12 450, taux de rebond 32 (%), sessions 4 800, durée moy 2.4 (affichée comme float). --gradient-primary en bleu-violet brand, duration à 1 200 ms pour un ressenti dynamique.
Fiche SaaS — Indicateurs de santé de la plateforme — Bento with Stats exemple 2

② Fiche SaaS — Indicateurs de santé de la plateforme

QuandUne carte récapitulative dans un dashboard produit ou une page de statut affiche l'uptime, la latence et les déploiements du mois.
PourquoiLe bento regroupe des métriques de nature différente (pourcentage, milliseconde, entier) dans un composant unifié lisible d'un seul regard — les barres de progression donnent immédiatement la lecture relative sans légende supplémentaire.
RéglagesCibles : uptime 99.9 (float), requêtes 245 (K), latence 48 (ms), déploiements 127. Gradient vert ou bleu pour les cellules positives, --fill-width à 99 % pour l'uptime, 48 % pour la latence.
Section "En chiffres" — Startup / page À propos — Bento with Stats exemple 3

③ Section "En chiffres" — Startup / page À propos

QuandUn site corporate ou une page investisseurs présente les chiffres phares de la société : clients, pays, satisfaction, croissance.
PourquoiL'entrée en scène des compteurs au défilement transforme une liste froide de statistiques en moment narratif — chaque chiffre « compte » littéralement devant le visiteur.
RéglagesCibles : clients 3 240, pays 28, satisfaction 97 (%), NPS 71. Palette plus sobre (--gradient-primary doré ou monochrome), --bg-card légèrement plus clair (#1a1a28) pour s'intégrer à un fond off-black.

Comment ça marche

La mise en page repose sur un CSS Grid à 4 colonnes et 3 lignes (.bento-stats) : cell-1 occupe 2 colonnes × 2 lignes, cell-2 2 colonnes, cell-3 et cell-4 1 colonne chacune, cell-5 et cell-6 2 colonnes. Les chiffres (.stat-number) utilisent -webkit-text-fill-color: transparent combiné à background-clip: text pour afficher le gradient --gradient-primary en forme de texte.

Un IntersectionObserver surveille l'élément #statsBento avec un seuil de 0,5 : quand la grille est visible à 50 % dans le viewport, la fonction animateStats() se déclenche une seule fois (l'observer se désabonne immédiatement via unobserve). Elle lit l'attribut data-target de chaque .stat-number pour connaître la valeur cible.

L'animation de chaque compteur est pilotée par un setInterval de 60 pas sur 1 500 ms. À chaque pas, current = (target / 60) × step. Si la valeur cible est décimale (target % 1 !== 0), le texte est formaté avec toFixed(1) ; sinon avec Math.floor. L'intervalle se nettoie lui-même à l'étape 60.

Les barres de progression (.stat-bar-fill) démarrent à width: 0 et passent à width: var(--fill-width) dès qu'une cellule reçoit le focus ou le survol (sélecteur CSS .bento-cell:hover .stat-bar-fill). La valeur --fill-width est définie en style inline sur chaque barre — aucun JS supplémentaire requis. La transition dure 1 s avec une courbe cubic-bezier(0.16, 1, 0.3, 1).

Accessibilité

  • prefers-reduced-motion non géré : le code source ne contient pas de vérification de ce media query. Les compteurs s'animent même si l'OS signale une préférence de réduction du mouvement. Ajoutez un guard if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; en tête de animateStats() pour le désactiver.
  • Aucun role ni aria-label sur le conteneur : les lecteurs d'écran peuvent annoncer les valeurs intermédiaires (0 → valeur finale) pendant l'animation. Envisagez aria-live="off" sur chaque .stat-number pour masquer les mises à jour dynamiques.
  • Le texte gradient (-webkit-text-fill-color: transparent) dépend de la luminosité du gradient choisi. Vérifiez un ratio ≥ 4,5:1 entre la teinte la plus sombre du gradient et le fond --bg-card (#12121a) avant de changer --gradient-primary.
  • Les barres de progression sont uniquement accessibles au survol souris. Les cellules n'étant pas focusables (tabindex absent), les utilisateurs clavier ne voient jamais les barres. Ajoutez :focus-within .stat-bar-fill si cet accès est requis.
  • Sans JavaScript, les chiffres restent à 0 et les barres restent masquées — aucune erreur JS fatale, la grille s'affiche correctement avec son fond et ses labels.

Compatibilité navigateur

Nécessite CSS Grid, CSS Custom Properties, IntersectionObserver et background-clip: text (préfixe -webkit- inclus). Zéro dépendance externe.

Chrome 88+✓ Complet
Firefox 87+✓ Complet
Safari 15+✓ Complet
Edge 88+✓ Complet
Mobile iOS✓ Complet
Android Chrome✓ Complet

Sans IntersectionObserver (navigateurs antérieurs à 2017), les compteurs ne démarrent pas — les chiffres restent à 0. Polyfill optionnel via @types/intersection-observer si un support IE11 est nécessaire. La grille et les barres restent visibles.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :

index.html — structure
<div class="demo-preview">
  <div class="bento-container">
    <div class="bento-grid bento-stats" id="statsBento">

      <!-- Cellule principale 2×2 -->
      <div class="bento-cell cell-1">
        <span class="stat-number" data-target="2847">0</span>
        <span class="stat-label">Label principal</span>
        <div class="stat-bar">
          <div class="stat-bar-fill" style="--fill-width: 95%;"></div>
        </div>
      </div>

      <!-- Cellule 2 colonnes -->
      <div class="bento-cell cell-2">
        <span class="stat-number" data-target="156">0</span>
        <span class="stat-label">Label</span>
      </div>

      <!-- Cellules 1 colonne -->
      <div class="bento-cell cell-3">
        <span class="stat-number" data-target="98">0</span>
        <span class="stat-label">%</span>
      </div>
      <div class="bento-cell cell-4">
        <span class="stat-number" data-target="42">0</span>
        <span class="stat-label">Label</span>
      </div>

      <!-- Cellules 2 colonnes avec barre -->
      <div class="bento-cell cell-5">
        <span class="stat-number" data-target="1.2">0</span>
        <span class="stat-label">M Label</span>
        <div class="stat-bar">
          <div class="stat-bar-fill" style="--fill-width: 72%;"></div>
        </div>
      </div>
      <div class="bento-cell cell-6">
        <span class="stat-number" data-target="4.9">0</span>
        <span class="stat-label">Note / 5</span>
        <div class="stat-bar">
          <div class="stat-bar-fill" style="--fill-width: 98%;"></div>
        </div>
      </div>

    </div>
  </div>
</div>
Débloquer le code complet — 9,90 € TTC/mois

Le code complet HTML + CSS + JS de Bento with Stats, prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
data-target valeur chiffrée Nombre affiché en fin d'animation sur chaque .stat-number. Entier → Math.floor ; décimal → toFixed(1). Exemples : 2847, 98, 1.2, 4.9.
--fill-width (inline) 95 %, 72 %, 98 % Largeur finale de la barre de progression, définie en style inline sur chaque .stat-bar-fill. Exemple : style="--fill-width: 75%".
--gradient-primary linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #d946ef 100%) Gradient appliqué aux chiffres (background-clip: text) et aux barres de progression. Remplacez par vos couleurs brand.
--bg-card #12121a Fond de chaque cellule bento. Augmentez légèrement la luminosité (#1c1c2a) pour un thème moins sombre.
--text-muted #8b8b93 Couleur des labels de statistiques (.stat-label). Utilisez une teinte plus claire si le fond de carte est plus sombre.
duration (JS, ligne const duration) 1500 Durée totale d'animation des compteurs en ms. 1 000 ms = vif et percutant, 2 000 ms = cinématique.
threshold (IntersectionObserver) 0.5 Fraction de visibilité de la grille requise avant déclenchement. 0 = dès qu'un pixel entre dans le viewport, 1 = grille entièrement visible.
grid-template-columns (.bento-stats) repeat(4, 1fr) Nombre et proportion des colonnes. Passez à repeat(3, 1fr) pour une grille plus compacte (adaptez les grid-column: span N des cellules en conséquence).

FAQ

Une seule fois. L'IntersectionObserver appelle statsObserver.unobserve(entry.target) dès le premier déclenchement — les compteurs ne repartent jamais de zéro, même si l'utilisateur scrolle au-delà puis revient sur la grille.
Ajoutez un <div class="bento-cell cell-N"> avec un .stat-number[data-target] et un .stat-label. Définissez son placement dans .bento-stats .cell-N via grid-column: span X et/ou grid-row: span Y. Si vous changez le nombre de colonnes (grid-template-columns), vérifiez que les spans restent cohérents avec la nouvelle grille.
Pas directement via une API publique — la fonction animateStats est encapsulée dans l'IIFE. Exposez-la vous-même : déplacez la déclaration en dehors de l'IIFE (window.animateStats = function() { … }) ou appelez document.dispatchEvent(new Event('resetStats')) en écoutant cet événement avant de relancer l'animation après avoir remis les chiffres à 0.