Design & UX

Tutoriel : Créer des graphiques et charts pour le web

18 min de lecture

Pourquoi la data visualization est essentielle en 2025

Un tableau de 500 lignes est incompréhensible. Le même dataset présenté en graphique raconte une histoire en 2 secondes. La data visualization transforme les données brutes en insights actionnables — et c’est une compétence de plus en plus demandée. Au Sénégal, les startups, ONG et administrations collectent des tonnes de données mais manquent de compétences pour les visualiser efficacement.

Chart.js : la bibliothèque la plus accessible

Chart.js est la bibliothèque de graphiques la plus utilisée au monde. Simple, légère (73 Ko gzip), responsive, et supporte 8 types de graphiques par défaut.

Installation et premier graphique

<!-- CDN : aucune installation nécessaire -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<canvas id="myChart" width="400" height="200"></canvas>

<script>
const ctx = document.getElementById('myChart').getContext('2d');

new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Jun'],
    datasets: [{
      label: 'Revenus (FCFA)',
      data: [450000, 520000, 680000, 590000, 820000, 950000],
      backgroundColor: '#3B82F6',
      borderRadius: 8,
    }]
  },
  options: {
    responsive: true,
    plugins: {
      legend: { display: false },
      title: {
        display: true,
        text: 'Revenus mensuels - Premier semestre'
      }
    },
    scales: {
      y: {
        ticks: {
          callback: (v) => v.toLocaleString('fr-FR') + ' F'
        }
      }
    }
  }
});
</script>

Types de graphiques et quand les utiliser

  • Bar (barres) — Comparer des catégories. Ex : revenus par mois, utilisateurs par pays
  • Line (lignes) — Montrer une évolution dans le temps. Ex : trafic web, croissance CA
  • Pie / Doughnut (camembert) — Montrer des proportions. Ex : répartition des sources de trafic. Limitez à 5-6 segments maximum
  • Radar — Comparer des profils multi-critères. Ex : compétences techniques d’un candidat
  • Scatter (nuage de points) — Montrer la corrélation entre deux variables
  • Area (aire) — Comme line mais avec l’aire remplie. Montre le volume en plus de la tendance

Graphique ligne avec données réelles

new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Sem 1', 'Sem 2', 'Sem 3', 'Sem 4', 'Sem 5', 'Sem 6'],
    datasets: [
      {
        label: 'Visiteurs site',
        data: [1200, 1900, 3000, 5000, 4200, 6100],
        borderColor: '#3B82F6',
        backgroundColor: 'rgba(59,130,246,0.1)',
        fill: true,
        tension: 0.4, // Courbe lissée
      },
      {
        label: 'Conversions',
        data: [45, 78, 120, 210, 185, 290],
        borderColor: '#10B981',
        backgroundColor: 'rgba(16,185,129,0.1)',
        fill: true,
        tension: 0.4,
      }
    ]
  },
  options: {
    responsive: true,
    interaction: {
      mode: 'index',
      intersect: false, // Tooltip sur toute la colonne
    },
    plugins: {
      tooltip: {
        callbacks: {
          label: (ctx) => ctx.dataset.label + ': ' + ctx.parsed.y.toLocaleString('fr-FR')
        }
      }
    }
  }
});

D3.js : la puissance maximale

D3.js (Data-Driven Documents) est LA bibliothèque de référence pour la data visualization avancée. Elle manipule le DOM directement et permet de créer n’importe quel type de visualisation — y compris des cartes, des graphiques interactifs et des animations de données.

Quand choisir D3 plutôt que Chart.js :

  • Visualisations personnalisées (treemaps, sankey diagrams, chord diagrams)
  • Cartes géographiques interactives (carte du Sénégal par région)
  • Animations complexes de données
  • Contrôle pixel-perfect sur chaque élément
// D3.js : bar chart SVG
import * as d3 from 'd3';

const data = [
  { region: 'Dakar', population: 3900000 },
  { region: 'Thiès', population: 2100000 },
  { region: 'Diourbel', population: 1800000 },
  { region: 'Saint-Louis', population: 1100000 },
  { region: 'Kaolack', population: 1050000 },
];

const width = 600, height = 400, margin = { t: 20, r: 20, b: 40, l: 100 };

const svg = d3.select('#chart')
  .append('svg')
  .attr('viewBox', `0 0 ${width} ${height}`);

const x = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.population)])
  .range([margin.l, width - margin.r]);

const y = d3.scaleBand()
  .domain(data.map(d => d.region))
  .range([margin.t, height - margin.b])
  .padding(0.3);

// Barres
svg.selectAll('rect')
  .data(data)
  .join('rect')
  .attr('x', margin.l)
  .attr('y', d => y(d.region))
  .attr('width', d => x(d.population) - margin.l)
  .attr('height', y.bandwidth())
  .attr('fill', '#3B82F6')
  .attr('rx', 4);

// Labels
svg.selectAll('.label')
  .data(data)
  .join('text')
  .attr('x', margin.l - 8)
  .attr('y', d => y(d.region) + y.bandwidth() / 2)
  .attr('text-anchor', 'end')
  .attr('dominant-baseline', 'middle')
  .text(d => d.region);

Alternatives modernes

Recharts (React)

import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';

const data = [
  { mois: 'Jan', revenus: 450000 },
  { mois: 'Fév', revenus: 520000 },
  { mois: 'Mar', revenus: 680000 },
];

function RevenueChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <BarChart data={data}>
        <XAxis dataKey="mois" />
        <YAxis tickFormatter={(v) => (v/1000) + 'K'} />
        <Tooltip formatter={(v) => v.toLocaleString('fr-FR') + ' FCFA'} />
        <Bar dataKey="revenus" fill="#3B82F6" radius={[8,8,0,0]} />
      </BarChart>
    </ResponsiveContainer>
  );
}

ApexCharts (framework-agnostique)

ApexCharts offre un excellent compromis entre la simplicité de Chart.js et la puissance de D3. Interactivité riche par défaut (zoom, pan, export PNG/SVG), animations fluides, et une API déclarative. Idéal pour les dashboards d’entreprise.

Observable Plot (le plus simple)

import * as Plot from '@observablehq/plot';

// Un graphique en UNE ligne
const chart = Plot.barY(data, {x: 'mois', y: 'revenus', fill: '#3B82F6'}).plot();
document.querySelector('#chart').append(chart);

Bonnes pratiques de data visualization

  • Commencez par la question — « Quelle information le lecteur doit-il retenir ? » dicte le type de graphique. Ne choisissez pas le type par esthétique
  • Simplifiez — Supprimez les gridlines inutiles, les légendes évidentes, les bordures décoratives. Chaque pixel doit servir la compréhension
  • Couleurs intentionnelles — Utilisez la couleur pour mettre en avant, pas pour décorer. Gris par défaut, couleur d’accent pour les données importantes
  • Annotations — Ajoutez du texte directement sur le graphique pour guider l’interprétation. « Pic de trafic après la campagne Facebook » est plus utile qu’un point de données isolé
  • Responsive — Les graphiques doivent être lisibles sur mobile. Utilisez des conteneurs SVG avec viewBox ou ResponsiveContainer
  • Accessibilité — Ne transmettez jamais l’information uniquement par la couleur (daltonisme). Ajoutez des patterns, labels directs, et un tableau de données en alternative
  • Format des nombres — Au Sénégal, utilisez le format français : 1 250 000 FCFA (espace comme séparateur de milliers, pas de virgule)

Cas pratique : dashboard analytics

Un dashboard type pour un site e-commerce sénégalais combine plusieurs graphiques :

  • KPI cards en haut : CA du jour, nombre de commandes, panier moyen, taux de conversion — pas des graphiques mais des chiffres grands et lisibles
  • Line chart : Évolution du CA sur 30 jours avec comparaison période précédente
  • Bar chart horizontal : Top 10 produits vendus
  • Doughnut : Répartition des modes de paiement (Wave 45%, Orange Money 30%, Carte 15%, Espèces 10%)
  • Heatmap : Heures et jours de la semaine avec le plus de commandes
  • Table : Dernières commandes avec statut (en cours, livrée, annulée)

La data visualization n’est pas un exercice artistique — c’est un outil de communication. Le meilleur graphique est celui qui transmet son message en moins de 5 secondes, sans que le lecteur ait besoin de réfléchir. Maîtrisez Chart.js pour 80% de vos besoins, et apprenez D3.js quand vous avez besoin de visualisations sur mesure.

Etape 1 : choisir la bonne bibliotheque selon le besoin

Avant d’ecrire la moindre ligne, clarifiez le contexte. Pour un tableau de bord interne avec quelques courbes et histogrammes, Chart.js suffit largement et pese 60 Ko gzippe. Pour une visualisation interactive complexe avec zoom, brushing et animations sur-mesure, D3.js reste la reference malgre une courbe d’apprentissage plus raide. Pour les graphiques financiers, lightweight-charts de TradingView est imbattable.

Une regle pratique pour un editeur a Dakar ou Abidjan facturant en FCFA : tant que vos donnees tiennent dans un CSV de moins de 5 000 lignes et que vos utilisateurs sont sur Mixx by Yas en 3G, Chart.js est le choix par defaut. Vous economisez deux jours de developpement par ecran, soit environ 65 596 FCFA de prestation au taux 1 EUR = 655,957 FCFA si vous facturez 100 EUR la journee.

Etape 2 : preparer un jeu de donnees CSV propre

Toute visualisation reussie commence par un CSV bien forme. Premiere ligne, les en-tetes sans espaces ni accents (par exemple mois,ventes_fcfa,marge_pct). Une ligne par observation, pas de cellules fusionnees, encodage UTF-8 sans BOM, separateur virgule.

mois,ventes_fcfa,marge_pct
2026-01,12500000,18.4
2026-02,13800000,19.1
2026-03,11200000,17.6
2026-04,15400000,21.2

Avant d’aller plus loin, validez le fichier avec csvlint votre.csv ou ouvrez-le dans VS Code avec l’extension Rainbow CSV. Une virgule oubliee ligne 47 fait planter le rendu sans message d’erreur explicite, et vous perdez deux heures a chercher.

Etape 3 : poser le squelette HTML et charger Chart.js

Creez une page minimale avec un canvas et le script Chart.js charge depuis un CDN reconnu. Le canvas reserve la zone de dessin, le script importe la bibliotheque, et l’attribut defer empeche le blocage du rendu initial.

<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>Ventes mensuelles</title>
</head>
<body>
  <canvas id="ventes" width="800" height="400"></canvas>
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.6/dist/chart.umd.min.js" defer></script>
  <script src="./graph.js" defer></script>
</body>
</html>

Apres ouverture dans le navigateur, la page doit afficher un canvas vide sans erreur dans la console. Si Chart.js n’est pas charge, vous verrez « Chart is not defined » — verifiez la balise script et l’URL du CDN.

Etape 4 : tracer un premier graphique en barres

Le script graph.js lit le CSV, parse les valeurs et construit la configuration Chart.js. Pour rester simple, integrez les donnees en dur dans cette etape, le chargement dynamique viendra apres.

const ctx = document.getElementById('ventes').getContext('2d');
new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ['Janv', 'Fev', 'Mars', 'Avril'],
    datasets: [{
      label: 'Ventes (FCFA)',
      data: [12500000, 13800000, 11200000, 15400000],
      backgroundColor: '#1c7c54'
    }]
  },
  options: { responsive: true, maintainAspectRatio: false }
});

Le graphique apparait avec quatre barres vertes. Si rien ne s’affiche, ouvrez la console et cherchez l’erreur « Cannot read properties of null » — elle signifie que le canvas n’existe pas au moment de l’execution. Solution : verifiez que graph.js est bien charge avec defer apres Chart.js.

Etape 5 : charger les donnees depuis un CSV distant

En production vous voulez separer les donnees du code. Utilisez fetch et la bibliotheque PapaParse pour lire un CSV servi depuis votre API ou un dossier statique.

async function chargerVentes() {
  const r = await fetch('/data/ventes-2026.csv');
  const txt = await r.text();
  const rows = Papa.parse(txt, { header: true, dynamicTyping: true }).data;
  return rows.filter(x => x.mois);
}

chargerVentes().then(rows => {
  new Chart(document.getElementById('ventes'), {
    type: 'line',
    data: {
      labels: rows.map(r => r.mois),
      datasets: [{ label: 'Ventes', data: rows.map(r => r.ventes_fcfa), borderColor: '#1c7c54' }]
    }
  });
});

Au rechargement, le graphique se construit a partir du fichier distant. Si vous voyez une courbe plate a zero, le parsing a echoue — verifiez que dynamicTyping: true est bien actif et que les valeurs CSV ne sont pas entourees de guillemets parasites.

Etape 6 : formater les axes pour des montants en FCFA

Par defaut Chart.js affiche les valeurs brutes (12500000), illisibles. Configurez un formateur pour afficher « 12,5 M FCFA ». Le callback ticks.callback intercepte chaque etiquette d’axe.

options: {
  scales: {
    y: {
      ticks: {
        callback: v => (v / 1000000).toFixed(1) + ' M FCFA'
      }
    }
  }
}

L’axe Y affiche maintenant « 12.5 M FCFA », « 13.8 M FCFA », etc. Pour les tooltips, ajoutez un callback similaire dans plugins.tooltip.callbacks.label. Cette etape est cruciale pour des tableaux de bord destines a une direction commerciale a Dakar : les chiffres en FCFA bruts sont quasi illisibles passe le million.

Etape 7 : passer a D3 pour les visualisations sur-mesure

Quand le besoin depasse les types standards (treemap, sankey, force-directed graph), Chart.js montre ses limites. D3 demande plus de code mais offre un controle total. Voici un squelette pour un nuage de points avec axes manuels.

import * as d3 from 'd3';

const svg = d3.select('#scatter').append('svg').attr('width', 800).attr('height', 400);
const x = d3.scaleLinear().domain([0, 100]).range([40, 780]);
const y = d3.scaleLinear().domain([0, 1]).range([380, 20]);

svg.append('g').attr('transform', 'translate(0,380)').call(d3.axisBottom(x));
svg.append('g').attr('transform', 'translate(40,0)').call(d3.axisLeft(y));

d3.csv('/data/correlation.csv').then(data => {
  svg.selectAll('circle').data(data).join('circle')
    .attr('cx', d => x(+d.score))
    .attr('cy', d => y(+d.taux))
    .attr('r', 4)
    .attr('fill', '#1c7c54');
});

Le nuage de points s’affiche avec axes propres. Si les points sont tous superposes en bas a gauche, vos echelles sont mal calees — utilisez d3.extent(data, d => +d.score) pour deduire automatiquement les bornes a partir des donnees reelles.

Etape 8 : rendre le graphique accessible et imprimable

Un graphique web n’est pas qu’une image. Ajoutez un aria-label descriptif sur le canvas, fournissez un tableau HTML equivalent en dessous (cache visuellement avec visually-hidden) et exposez les donnees brutes via un bouton « Telecharger CSV ». Les lecteurs d’ecran lisent ainsi le contenu et les utilisateurs peuvent reutiliser le jeu de donnees.

Pour l’impression et le PDF, declenchez un export PNG via chart.toBase64Image(). Combine avec une fonction d’export tableau, vous offrez trois formats utilisables : graphique a l’ecran, image dans un rapport et CSV pour analyse Excel. Lectures complémentaires, lisez aussi creer un tableau de bord temps reel et le guide optimiser les performances web.

Etape 9 : optimiser le poids et le temps de rendu en 3G

Sur Mixx by Yas a Pikine ou MTN Cote d’Ivoire en 3G, chaque kilooctet compte. Ne chargez Chart.js et D3 que sur les pages qui en ont reellement besoin via un import dynamique : const { Chart } = await import('chart.js'). Vous economisez 60 a 200 Ko sur les pages sans graphique.

Activez aussi parsing: false dans Chart.js quand vous fournissez des donnees deja au format {x, y}, ce qui divise par trois le temps de premier rendu sur des series de 5 000 points. Mesurez avec Lighthouse Mobile : viser un Time to Interactive sous 3,5 secondes en 3G simule.

Étape 1 : choisir la bonne librairie de graphiques pour votre cas d’usage

Trois grandes familles de librairies cohabitent en 2026 et méritent d’être comparées avant d’en intégrer une. Chart.js est la plus simple à prendre en main, idéale pour des dashboards internes (suivi de ventes Wave, statistiques d’inscription à une formation, KPI mensuels). ECharts d’Apache offre une richesse de visualisations bien plus large (graphes orientés, treemaps, sankeys) et brille pour les rapports analytiques. D3.js est la plus puissante mais aussi la plus exigeante — utile uniquement quand vous voulez une visualisation totalement sur mesure.

Pour 80 % des sites web ouest-africains que nous accompagnons (tableaux de bord d’ONG, suivi de chiffre d’affaires d’un commerce en FCFA, courbes de fréquentation d’un blog), Chart.js suffit largement. Ce tutoriel l’utilise comme base. Vous saurez en revanche reconnaître quand basculer sur ECharts ou D3.

Étape 2 : préparer votre page HTML et installer Chart.js

Créez un fichier dashboard.html avec une structure minimale et un <canvas> qui hébergera le graphique. Évitez les CDN obscurs : utilisez celui de jsDelivr qui est rapide depuis l’Afrique de l’Ouest grâce à ses points de présence à Lagos et Johannesburg.

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <title>Tableau de bord ventes</title>
  <style>
    body { font-family: system-ui; max-width: 900px; margin: 2rem auto; padding: 0 1rem; }
    .chart-card { background: #fff; padding: 1.5rem; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
  </style>
</head>
<body>
  <div class="chart-card">
    <canvas id="ventesMois" width="800" height="400"></canvas>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
  <script src="app.js"></script>
</body>
</html>

Vous saurez que tout fonctionne quand : vous ouvrez la page dans Chrome et la zone du canvas s’affiche en blanc, sans erreur 404 dans l’onglet Network de DevTools.

Étape 3 : tracer un premier graphique en barres

Dans app.js, écrivez le code minimal pour afficher les ventes mensuelles d’une boutique fictive en FCFA. Le but est de comprendre la structure d’une configuration Chart.js : type, data (labels + datasets), options.

const ctx = document.getElementById('ventesMois');

new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin'],
    datasets: [{
      label: 'Ventes (FCFA)',
      data: [1200000, 1450000, 1620000, 1380000, 1900000, 2150000],
      backgroundColor: '#0a7c3a'
    }]
  },
  options: {
    responsive: true,
    plugins: {
      legend: { position: 'top' },
      title: { display: true, text: 'Ventes 2026 — Boutique Téranga' }
    },
    scales: {
      y: {
        beginAtZero: true,
        ticks: { callback: v => (v/1000) + ' k FCFA' }
      }
    }
  }
});

Rechargez. Vous voyez six barres vertes croissantes. La conversion en milliers (k FCFA) sur l’axe Y évite l’affichage de « 2 150 000 » à chaque tick. Pour rappel, 2 150 000 FCFA équivaut à 3 277,03 EUR au taux fixe 1 EUR = 655,957 FCFA.

Étape 4 : passer en graphique linéaire et gérer plusieurs séries

Pour comparer ventes et coûts, un line chart est plus parlant qu’un bar chart. Modifiez le type et ajoutez un second dataset.

new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Jan','Fév','Mar','Avr','Mai','Juin'],
    datasets: [
      { label: 'Ventes', data: [1200000,1450000,1620000,1380000,1900000,2150000],
        borderColor: '#0a7c3a', backgroundColor: 'rgba(10,124,58,0.15)', tension: 0.3, fill: true },
      { label: 'Coûts', data: [800000,910000,1050000,920000,1180000,1300000],
        borderColor: '#c0392b', borderDash: [6, 4], tension: 0.3 }
    ]
  },
  options: { responsive: true, interaction: { mode: 'index', intersect: false } }
});

L’option interaction: { mode: 'index' } est essentielle : au survol, l’utilisateur voit les deux valeurs alignées sur le même mois dans le tooltip. La preuve que ça tourne : le tooltip affiche bien « Ventes : 1 900 000 » et « Coûts : 1 180 000 » simultanément en mai.

Étape 5 : alimenter le graphique depuis une vraie source de données

Les chiffres en dur ne servent à rien en production. Branchez le graphique sur votre API ou sur un fichier CSV exporté depuis votre ERP, votre boutique WooCommerce ou votre Google Sheet.

async function chargerVentes() {
  const r = await fetch('/api/ventes-mensuelles?annee=2026');
  if (!r.ok) throw new Error('Erreur ' + r.status);
  return r.json(); // attendu: [{mois:'Jan', ventes:1200000, couts:800000}, ...]
}

(async () => {
  try {
    const rows = await chargerVentes();
    const labels = rows.map(r => r.mois);
    const ventes = rows.map(r => r.ventes);
    const couts  = rows.map(r => r.couts);
    new Chart(ctx, { type:'line', data:{ labels, datasets:[
      { label:'Ventes', data: ventes, borderColor:'#0a7c3a' },
      { label:'Coûts',  data: couts,  borderColor:'#c0392b' }
    ]}});
  } catch (e) {
    document.querySelector('.chart-card').innerHTML = 'Données indisponibles : ' + e.message;
  }
})();

Toujours gérer le cas d’erreur réseau — un dashboard qui affiche une zone vide sans message frustre l’utilisateur sur connexion 3G instable.

Étape 6 : rendre le graphique accessible et imprimable

Un graphique Chart.js est dessiné dans un canvas, donc invisible aux lecteurs d’écran. Compensez avec un tableau HTML caché qui contient les mêmes données, lié au canvas par aria-describedby.

<canvas id="ventesMois" aria-describedby="ventes-tableau"></canvas>
<table id="ventes-tableau" class="visually-hidden">
  <caption>Ventes mensuelles 2026 en FCFA</caption>
  <thead><tr><th>Mois</th><th>Ventes</th><th>Coûts</th></tr></thead>
  <tbody>
    <tr><td>Jan</td><td>1 200 000</td><td>800 000</td></tr>
    <!-- ... -->
  </tbody>
</table>

Pour l’export PNG (rapport mensuel à imprimer), Chart.js expose chart.toBase64Image(). Bouton « Télécharger » :

document.querySelector('#export').addEventListener('click', () => {
  const a = document.createElement('a');
  a.href = chart.toBase64Image('image/png', 1);
  a.download = 'ventes-2026.png';
  a.click();
});

Étape 7 : optimiser les performances quand les données grossissent

Au-delà de 5 000 points, Chart.js commence à ralentir sur mobile. Activez l’option parsing: false en pré-formatant vos données {x, y}, désactivez les animations, et utilisez la décimation (Largest Triangle Three Buckets) pour réduire l’échantillonnage visuellement sans perdre l’allure.

new Chart(ctx, {
  type: 'line',
  data: { datasets: [{ data: gros_dataset, parsing: false }] },
  options: {
    animation: false,
    plugins: {
      decimation: { enabled: true, algorithm: 'lttb', samples: 500 }
    }
  }
});

Le marqueur de succès : le rendu initial passe sous 200 ms même avec 50 000 points sur un téléphone d’entrée de gamme.

Étape 8 : intégrer le graphique dans WordPress, React ou Vue

Pour WordPress, créez un shortcode [chart-ventes] qui injecte le canvas et charge Chart.js conditionnellement (uniquement quand le shortcode est utilisé sur une page). Pour React, utilisez react-chartjs-2 qui wrapper le tout en composant. Pour Vue, vue-chartjs joue le même rôle.

// React + react-chartjs-2
import { Bar } from 'react-chartjs-2';
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);

export default function VentesChart({ data }) {
  return <Bar data={data} options={{ responsive: true }} />;
}

Quel que soit le framework, retenez la règle : un seul graphique par « above the fold » pour ne pas saturer le CPU au chargement, et lazy-load les autres au scroll.

Sur un angle proche sur la mise en page d’un dashboard web, consultez notre tutoriel sur la conception d’un tableau de bord moderne en CSS Grid, et pour la dimension data le guide SQL pour produire les KPI mensuels d’un commerce.

Partager