Open demo

CSS code

HTML
<div><span class="lbl">KPI cards with sparklines</span>
<div class="kpi-set">
  <article class="kpi">
    <div class="kpi-head"><h3 class="kpi-label">Net revenue</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">$89,412</p>
    <p class="kpi-foot"><span class="kpi-delta is-good"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+12.4%</span>up from $79,540 in Sep</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 33L8.6 28.9L17.1 31.6L25.7 23.5L34.3 26.2L42.9 20.7L51.4 16.6L60 22.1L68.6 18L77.1 12.5L85.7 15.3L94.3 9.8L102.9 5.7L111.4 11.2L120 3L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 33L8.6 28.9L17.1 31.6L25.7 23.5L34.3 26.2L42.9 20.7L51.4 16.6L60 22.1L68.6 18L77.1 12.5L85.7 15.3L94.3 9.8L102.9 5.7L111.4 11.2L120 3"/></svg>
  </article>
  <article class="kpi">
    <div class="kpi-head"><h3 class="kpi-label">Active subscribers</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">3,482</p>
    <p class="kpi-foot"><span class="kpi-delta is-good"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+4.1%</span>up from 3,345 on Oct 1</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 33L8.6 30.4L17.1 27.6L25.7 28.1L34.3 24.3L42.9 22.2L51.4 19.9L60 17.1L68.6 17.7L77.1 13.8L85.7 11L94.3 8.8L102.9 6.7L111.4 5.1L120 3L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 33L8.6 30.4L17.1 27.6L25.7 28.1L34.3 24.3L42.9 22.2L51.4 19.9L60 17.1L68.6 17.7L77.1 13.8L85.7 11L94.3 8.8L102.9 6.7L111.4 5.1L120 3"/></svg>
  </article>
  <article class="kpi">
    <div class="kpi-head"><h3 class="kpi-label">Monthly churn</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">2.3%</p>
    <p class="kpi-foot"><span class="kpi-delta is-good"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>−0.4 pts</span>down from 2.7%, lower is better</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 3L8.6 8L17.1 8L25.7 13L34.3 13L42.9 18L51.4 18L60 23L68.6 18L77.1 23L85.7 28L94.3 28L102.9 33L111.4 28L120 33L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 3L8.6 8L17.1 8L25.7 13L34.3 13L42.9 18L51.4 18L60 23L68.6 18L77.1 23L85.7 28L94.3 28L102.9 33L111.4 28L120 33"/></svg>
  </article>
  <article class="kpi">
    <div class="kpi-head"><h3 class="kpi-label">Avg. order value</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">$62.40</p>
    <p class="kpi-foot"><span class="kpi-delta is-bad"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>−3.2%</span>down from $64.46 in Sep</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 3L8.6 8.4L17.1 4.5L25.7 13L34.3 17.6L42.9 12.2L51.4 21.5L60 19.9L68.6 26.1L77.1 28.4L85.7 23.8L94.3 30.7L102.9 27.6L111.4 33L120 31.5L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 3L8.6 8.4L17.1 4.5L25.7 13L34.3 17.6L42.9 12.2L51.4 21.5L60 19.9L68.6 26.1L77.1 28.4L85.7 23.8L94.3 30.7L102.9 27.6L111.4 33L120 31.5"/></svg>
  </article>
</div></div>

<div><span class="lbl">Compact tiles with icons</span>
<div class="kpi-set">
  <article class="kpi is-tile">
    <span class="kpi-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M19 8v6M22 11h-6"/></svg></span>
    <div class="kpi-body"><h3 class="kpi-label">New signups</h3><p class="kpi-value">412</p>
      <p class="kpi-trend is-good"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 18% this week</p></div>
  </article>
  <article class="kpi is-tile">
    <span class="kpi-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3a2 2 0 0 0 0-4z"/><path d="M13 5v2M13 11v2M13 17v2"/></svg></span>
    <div class="kpi-body"><h3 class="kpi-label">Open tickets</h3><p class="kpi-value">37</p>
      <p class="kpi-trend is-good"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>Down 9 since Monday</p></div>
  </article>
  <article class="kpi is-tile">
    <span class="kpi-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg></span>
    <div class="kpi-body"><h3 class="kpi-label">First response</h3><p class="kpi-value">1h 42m</p>
      <p class="kpi-trend is-bad"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 12m, slower</p></div>
  </article>
  <article class="kpi is-tile">
    <span class="kpi-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2l3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.2-6.2 3.2L7 14.2 2 9.3l6.9-1z"/></svg></span>
    <div class="kpi-body"><h3 class="kpi-label">Net promoter score</h3><p class="kpi-value">61</p>
      <p class="kpi-trend is-good"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 4 pts on Q3</p></div>
  </article>
</div></div>

<div><span class="lbl">Hero metric with breakdown</span>
<div class="kpi-set">
  <article class="kpi-hero">
    <div class="kpi-body">
      <div class="kpi-head"><h3 class="kpi-label">Monthly recurring revenue</h3><span class="kpi-period">October 2026</span></div>
      <p class="kpi-value">$128,940</p>
      <p class="kpi-foot"><span class="kpi-delta is-good"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+4.1%</span>up $5,080 from $123,860 in September</p>
    </div>
    <div class="kpi-chart">
      <svg viewBox="0 0 300 72" preserveAspectRatio="none" aria-hidden="true" class="kpi-spark"><path class="ar" d="M0 69L60 56.5L120 46.6L180 33.8L240 16.6L300 3L300 72L0 72Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 69L60 56.5L120 46.6L180 33.8L240 16.6L300 3"/></svg>
      <p class="kpi-axis"><span>May $104.2k</span><span>Oct $128.9k</span></p>
    </div>
    <ul class="kpi-split" aria-label="MRR movement in October">
      <li>New business<strong>+$9,820</strong></li>
      <li>Expansion<strong>+$3,410</strong></li>
      <li>Contraction<strong>−$1,620</strong></li>
      <li>Churned<strong>−$6,530</strong></li>
    </ul>
  </article>
</div></div>
CSS
/* KPI stat widgets. Direction is carried by the sign, the arrow shape and the wording, never by colour alone.
   Sparklines are decorative (aria-hidden): the number and the delta beside them say what they show. */
.kpi-set{--kpi-bg:#fff;--kpi-ink:#0f172a;--kpi-muted:#4b5768;--kpi-line:#e2e8f0;--kpi-accent:#2a78d6;
  --kpi-good:#15803d;--kpi-good-bg:#dcfce7;--kpi-bad:#b91c1c;--kpi-bad-bg:#fee2e2;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;color:var(--kpi-ink)}
.kpi{background:var(--kpi-bg);border:1px solid var(--kpi-line);border-radius:16px;padding:18px 18px 16px;
  box-shadow:0 1px 2px rgba(15,23,42,.04),0 8px 24px rgba(15,23,42,.05);display:flex;flex-direction:column;gap:6px;min-width:0}
.kpi-head{display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.kpi-label{font-size:.84rem;font-weight:600;color:var(--kpi-muted)}
.kpi-period{font-size:.74rem;color:var(--kpi-muted);white-space:nowrap}
.kpi-value{font-size:1.85rem;font-weight:750;letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.15}
.kpi-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.8rem;color:var(--kpi-muted)}
.kpi-delta{display:inline-flex;align-items:center;gap:3px;padding:2px 8px 2px 6px;border-radius:999px;font-weight:700;
  font-size:.78rem;font-variant-numeric:tabular-nums}
.kpi-delta svg{width:14px;height:14px;flex:none}
.kpi-delta.is-good{color:var(--kpi-good);background:var(--kpi-good-bg)}
.kpi-delta.is-bad{color:var(--kpi-bad);background:var(--kpi-bad-bg)}
.kpi-spark{display:block;width:100%;height:40px;margin-top:6px;overflow:visible}
.kpi-spark .ln{fill:none;stroke:var(--kpi-accent);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.kpi-spark .ar{fill:var(--kpi-accent);opacity:.1}
/* compact tiles */
.kpi.is-tile{flex-direction:row;align-items:center;gap:14px;padding:16px}
.kpi-icon{flex:none;display:grid;place-items:center;width:44px;height:44px;border-radius:12px;background:#e8f1fc;color:#1f5fae}
.kpi-icon svg{width:22px;height:22px}
.kpi-body{min-width:0;display:flex;flex-direction:column;gap:2px}
.kpi.is-tile .kpi-value{font-size:1.4rem}
.kpi-trend{display:inline-flex;align-items:center;gap:4px;font-size:.78rem;font-weight:600;font-variant-numeric:tabular-nums}
.kpi-trend svg{width:14px;height:14px}
.kpi-trend.is-good{color:var(--kpi-good)}
.kpi-trend.is-bad{color:var(--kpi-bad)}
/* hero metric */
.kpi-hero{grid-column:1/-1;background:var(--kpi-bg);border:1px solid var(--kpi-line);border-radius:18px;padding:22px;
  box-shadow:0 1px 2px rgba(15,23,42,.04),0 8px 24px rgba(15,23,42,.05);display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:22px 28px}
.kpi-hero .kpi-value{font-size:2.6rem}
.kpi-chart{display:flex;flex-direction:column;justify-content:flex-end;gap:6px}
.kpi-chart svg{width:100%;height:90px;overflow:visible}
.kpi-axis{display:flex;justify-content:space-between;font-size:.72rem;color:var(--kpi-muted)}
.kpi-split{grid-column:1/-1;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;border-top:1px solid var(--kpi-line);padding-top:16px;list-style:none}
.kpi-split li{display:flex;flex-direction:column;gap:2px;font-size:.8rem;color:var(--kpi-muted)}
.kpi-split strong{font-size:1.05rem;color:var(--kpi-ink);font-variant-numeric:tabular-nums}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media (max-width:640px){.kpi-hero{grid-template-columns:1fr}.kpi-split{grid-template-columns:repeat(2,minmax(0,1fr))}.kpi-hero .kpi-value{font-size:2.1rem}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">KPI cards with sparklines</span>
<div class="kpi-set row row-cols-1 row-cols-sm-2 row-cols-lg-4 g-3">
  <div class="col"><article class="card h-100"><div class="card-body d-flex flex-column gap-1">
    <div class="d-flex justify-content-between align-items-baseline gap-2"><h3 class="kpi-label">Net revenue</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">$89,412</p>
    <p class="d-flex align-items-center flex-wrap gap-2 kpi-foot text-body-secondary mb-0"><span class="badge rounded-pill bg-success-subtle text-success-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+12.4%</span>up from $79,540 in Sep</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 33L8.6 28.9L17.1 31.6L25.7 23.5L34.3 26.2L42.9 20.7L51.4 16.6L60 22.1L68.6 18L77.1 12.5L85.7 15.3L94.3 9.8L102.9 5.7L111.4 11.2L120 3L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 33L8.6 28.9L17.1 31.6L25.7 23.5L34.3 26.2L42.9 20.7L51.4 16.6L60 22.1L68.6 18L77.1 12.5L85.7 15.3L94.3 9.8L102.9 5.7L111.4 11.2L120 3"/></svg>
  </div></article></div>
  <div class="col"><article class="card h-100"><div class="card-body d-flex flex-column gap-1">
    <div class="d-flex justify-content-between align-items-baseline gap-2"><h3 class="kpi-label">Active subscribers</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">3,482</p>
    <p class="d-flex align-items-center flex-wrap gap-2 kpi-foot text-body-secondary mb-0"><span class="badge rounded-pill bg-success-subtle text-success-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+4.1%</span>up from 3,345 on Oct 1</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 33L8.6 30.4L17.1 27.6L25.7 28.1L34.3 24.3L42.9 22.2L51.4 19.9L60 17.1L68.6 17.7L77.1 13.8L85.7 11L94.3 8.8L102.9 6.7L111.4 5.1L120 3L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 33L8.6 30.4L17.1 27.6L25.7 28.1L34.3 24.3L42.9 22.2L51.4 19.9L60 17.1L68.6 17.7L77.1 13.8L85.7 11L94.3 8.8L102.9 6.7L111.4 5.1L120 3"/></svg>
  </div></article></div>
  <div class="col"><article class="card h-100"><div class="card-body d-flex flex-column gap-1">
    <div class="d-flex justify-content-between align-items-baseline gap-2"><h3 class="kpi-label">Monthly churn</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">2.3%</p>
    <p class="d-flex align-items-center flex-wrap gap-2 kpi-foot text-body-secondary mb-0"><span class="badge rounded-pill bg-success-subtle text-success-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>−0.4 pts</span>down from 2.7%, lower is better</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 3L8.6 8L17.1 8L25.7 13L34.3 13L42.9 18L51.4 18L60 23L68.6 18L77.1 23L85.7 28L94.3 28L102.9 33L111.4 28L120 33L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 3L8.6 8L17.1 8L25.7 13L34.3 13L42.9 18L51.4 18L60 23L68.6 18L77.1 23L85.7 28L94.3 28L102.9 33L111.4 28L120 33"/></svg>
  </div></article></div>
  <div class="col"><article class="card h-100"><div class="card-body d-flex flex-column gap-1">
    <div class="d-flex justify-content-between align-items-baseline gap-2"><h3 class="kpi-label">Avg. order value</h3><span class="kpi-period">Oct 1–15</span></div>
    <p class="kpi-value">$62.40</p>
    <p class="d-flex align-items-center flex-wrap gap-2 kpi-foot text-body-secondary mb-0"><span class="badge rounded-pill bg-danger-subtle text-danger-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>−3.2%</span>down from $64.46 in Sep</p>
    <svg class="kpi-spark" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="ar" d="M0 3L8.6 8.4L17.1 4.5L25.7 13L34.3 17.6L42.9 12.2L51.4 21.5L60 19.9L68.6 26.1L77.1 28.4L85.7 23.8L94.3 30.7L102.9 27.6L111.4 33L120 31.5L120 36L0 36Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 3L8.6 8.4L17.1 4.5L25.7 13L34.3 17.6L42.9 12.2L51.4 21.5L60 19.9L68.6 26.1L77.1 28.4L85.7 23.8L94.3 30.7L102.9 27.6L111.4 33L120 31.5"/></svg>
  </div></article></div>
</div></div>

<div><span class="lbl">Compact tiles with icons</span>
<div class="kpi-set row row-cols-1 row-cols-sm-2 row-cols-lg-4 g-3">
  <div class="col"><article class="card h-100 kpi-tile"><div class="card-body d-flex align-items-center gap-3 p-3">
    <span class="kpi-icon flex-shrink-0 d-flex align-items-center justify-content-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M19 8v6M22 11h-6"/></svg></span>
    <div class="d-flex flex-column min-w-0"><h3 class="kpi-label">New signups</h3><p class="kpi-value">412</p>
      <p class="kpi-trend text-success-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 18% this week</p></div>
  </div></article></div>
  <div class="col"><article class="card h-100 kpi-tile"><div class="card-body d-flex align-items-center gap-3 p-3">
    <span class="kpi-icon flex-shrink-0 d-flex align-items-center justify-content-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3a2 2 0 0 0 0-4z"/><path d="M13 5v2M13 11v2M13 17v2"/></svg></span>
    <div class="d-flex flex-column min-w-0"><h3 class="kpi-label">Open tickets</h3><p class="kpi-value">37</p>
      <p class="kpi-trend text-success-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>Down 9 since Monday</p></div>
  </div></article></div>
  <div class="col"><article class="card h-100 kpi-tile"><div class="card-body d-flex align-items-center gap-3 p-3">
    <span class="kpi-icon flex-shrink-0 d-flex align-items-center justify-content-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg></span>
    <div class="d-flex flex-column min-w-0"><h3 class="kpi-label">First response</h3><p class="kpi-value">1h 42m</p>
      <p class="kpi-trend text-danger-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 12m, slower</p></div>
  </div></article></div>
  <div class="col"><article class="card h-100 kpi-tile"><div class="card-body d-flex align-items-center gap-3 p-3">
    <span class="kpi-icon flex-shrink-0 d-flex align-items-center justify-content-center"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2l3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.2-6.2 3.2L7 14.2 2 9.3l6.9-1z"/></svg></span>
    <div class="d-flex flex-column min-w-0"><h3 class="kpi-label">Net promoter score</h3><p class="kpi-value">61</p>
      <p class="kpi-trend text-success-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 4 pts on Q3</p></div>
  </div></article></div>
</div></div>

<div><span class="lbl">Hero metric with breakdown</span>
<div class="kpi-set">
  <article class="card kpi-hero"><div class="card-body">
    <div class="row g-4">
      <div class="col-md-6 d-flex flex-column gap-1">
        <div class="d-flex justify-content-between align-items-baseline gap-2"><h3 class="kpi-label">Monthly recurring revenue</h3><span class="kpi-period">October 2026</span></div>
        <p class="kpi-value">$128,940</p>
        <p class="d-flex align-items-center flex-wrap gap-2 kpi-foot text-body-secondary mb-0"><span class="badge rounded-pill bg-success-subtle text-success-emphasis"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+4.1%</span>up $5,080 from $123,860 in September</p>
      </div>
      <div class="col-md-6 d-flex flex-column justify-content-end gap-1">
        <svg viewBox="0 0 300 72" preserveAspectRatio="none" aria-hidden="true" class="kpi-spark"><path class="ar" d="M0 69L60 56.5L120 46.6L180 33.8L240 16.6L300 3L300 72L0 72Z"/><path class="ln" vector-effect="non-scaling-stroke" d="M0 69L60 56.5L120 46.6L180 33.8L240 16.6L300 3"/></svg>
        <p class="d-flex justify-content-between text-body-secondary mb-0" style="font-size:.72rem"><span>May $104.2k</span><span>Oct $128.9k</span></p>
      </div>
    </div>
    <ul class="kpi-split row row-cols-2 row-cols-md-4 g-3 list-unstyled border-top mt-3 mb-0 kpi-foot text-body-secondary" aria-label="MRR movement in October">
      <li class="col">New business<strong>+$9,820</strong></li>
      <li class="col">Expansion<strong>+$3,410</strong></li>
      <li class="col">Contraction<strong>−$1,620</strong></li>
      <li class="col">Churned<strong>−$6,530</strong></li>
    </ul>
  </div></article>
</div></div>
CSS
/* Bootstrap cards, grid and badges; colours come from Bootstrap's own variables, set once on .kpi-set. */
.kpi-set{--bs-body-color:#0f172a;--bs-secondary-color:#4b5768;--bs-border-color:#e2e8f0;--bs-card-border-color:#e2e8f0;
  --bs-success-text-emphasis:#15803d;--bs-success-bg-subtle:#dcfce7;--bs-danger-text-emphasis:#b91c1c;--bs-danger-bg-subtle:#fee2e2;--kpi-accent:#2a78d6;color:var(--bs-body-color)}
.kpi-set .card{--bs-card-border-color:#e2e8f0;--bs-card-border-radius:16px;--bs-card-spacer-x:18px;--bs-card-spacer-y:18px;box-shadow:0 1px 2px rgba(15,23,42,.04),0 8px 24px rgba(15,23,42,.05)}
.kpi-set .kpi-hero{--bs-card-border-radius:18px;--bs-card-spacer-x:22px;--bs-card-spacer-y:22px}
.kpi-label{font-size:.84rem;font-weight:600;color:var(--bs-secondary-color);margin:0}
.kpi-period{font-size:.74rem;color:var(--bs-secondary-color);white-space:nowrap}
.kpi-value{font-size:1.85rem;font-weight:750;letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.15;margin:0}
.kpi-tile .kpi-value{font-size:1.4rem}
.kpi-hero .kpi-value{font-size:2.6rem}
.kpi-set .badge{font-size:.78rem;font-weight:700;padding:3px 8px 3px 6px;display:inline-flex;align-items:center;gap:3px;font-variant-numeric:tabular-nums}
.kpi-set .badge svg,.kpi-trend svg{width:14px;height:14px;flex:none}
.kpi-trend{display:inline-flex;align-items:center;gap:4px;font-size:.78rem;font-weight:600;font-variant-numeric:tabular-nums;margin:0}
.kpi-spark{display:block;width:100%;height:40px;margin-top:6px;overflow:visible}
.kpi-hero .kpi-spark{height:90px}
.kpi-spark .ln{fill:none;stroke:var(--kpi-accent);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.kpi-spark .ar{fill:var(--kpi-accent);opacity:.1}
.kpi-icon{width:44px;height:44px;border-radius:12px;background:#e8f1fc;color:#1f5fae}
.kpi-icon svg{width:22px;height:22px}
.kpi-split strong{display:block;font-size:1.05rem;color:var(--bs-body-color);font-variant-numeric:tabular-nums}
.kpi-tile .min-w-0{min-width:0}
.kpi-foot{font-size:.8rem}
@media (max-width:575.98px){.kpi-hero .kpi-value{font-size:2.1rem}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#4b5768] uppercase">KPI cards with sparklines</span>
<div class="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-4 text-kpi-ink">
  <article class="flex min-w-0 flex-col gap-1.5 rounded-2xl border border-kpi-line bg-white px-[18px] pt-[18px] pb-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <div class="flex items-baseline justify-between gap-2"><h3 class="text-[.84rem] font-semibold text-kpi-muted">Net revenue</h3><span class="text-[.74rem] whitespace-nowrap text-kpi-muted">Oct 1–15</span></div>
    <p class="text-[1.85rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">$89,412</p>
    <p class="flex flex-wrap items-center gap-2 text-[.8rem] text-kpi-muted"><span class="inline-flex items-center gap-[3px] rounded-full bg-kpi-good-bg py-0.5 pr-2 pl-1.5 text-[.78rem] font-bold text-kpi-good tabular-nums"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+12.4%</span>up from $79,540 in Sep</p>
    <svg class="mt-1.5 block h-10 w-full overflow-visible" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="fill-kpi-accent opacity-10" d="M0 33L8.6 28.9L17.1 31.6L25.7 23.5L34.3 26.2L42.9 20.7L51.4 16.6L60 22.1L68.6 18L77.1 12.5L85.7 15.3L94.3 9.8L102.9 5.7L111.4 11.2L120 3L120 36L0 36Z"/><path class="fill-none stroke-kpi-accent stroke-2 [stroke-linecap:round] [stroke-linejoin:round]" vector-effect="non-scaling-stroke" d="M0 33L8.6 28.9L17.1 31.6L25.7 23.5L34.3 26.2L42.9 20.7L51.4 16.6L60 22.1L68.6 18L77.1 12.5L85.7 15.3L94.3 9.8L102.9 5.7L111.4 11.2L120 3"/></svg>
  </article>
  <article class="flex min-w-0 flex-col gap-1.5 rounded-2xl border border-kpi-line bg-white px-[18px] pt-[18px] pb-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <div class="flex items-baseline justify-between gap-2"><h3 class="text-[.84rem] font-semibold text-kpi-muted">Active subscribers</h3><span class="text-[.74rem] whitespace-nowrap text-kpi-muted">Oct 1–15</span></div>
    <p class="text-[1.85rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">3,482</p>
    <p class="flex flex-wrap items-center gap-2 text-[.8rem] text-kpi-muted"><span class="inline-flex items-center gap-[3px] rounded-full bg-kpi-good-bg py-0.5 pr-2 pl-1.5 text-[.78rem] font-bold text-kpi-good tabular-nums"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+4.1%</span>up from 3,345 on Oct 1</p>
    <svg class="mt-1.5 block h-10 w-full overflow-visible" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="fill-kpi-accent opacity-10" d="M0 33L8.6 30.4L17.1 27.6L25.7 28.1L34.3 24.3L42.9 22.2L51.4 19.9L60 17.1L68.6 17.7L77.1 13.8L85.7 11L94.3 8.8L102.9 6.7L111.4 5.1L120 3L120 36L0 36Z"/><path class="fill-none stroke-kpi-accent stroke-2 [stroke-linecap:round] [stroke-linejoin:round]" vector-effect="non-scaling-stroke" d="M0 33L8.6 30.4L17.1 27.6L25.7 28.1L34.3 24.3L42.9 22.2L51.4 19.9L60 17.1L68.6 17.7L77.1 13.8L85.7 11L94.3 8.8L102.9 6.7L111.4 5.1L120 3"/></svg>
  </article>
  <article class="flex min-w-0 flex-col gap-1.5 rounded-2xl border border-kpi-line bg-white px-[18px] pt-[18px] pb-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <div class="flex items-baseline justify-between gap-2"><h3 class="text-[.84rem] font-semibold text-kpi-muted">Monthly churn</h3><span class="text-[.74rem] whitespace-nowrap text-kpi-muted">Oct 1–15</span></div>
    <p class="text-[1.85rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">2.3%</p>
    <p class="flex flex-wrap items-center gap-2 text-[.8rem] text-kpi-muted"><span class="inline-flex items-center gap-[3px] rounded-full bg-kpi-good-bg py-0.5 pr-2 pl-1.5 text-[.78rem] font-bold text-kpi-good tabular-nums"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>−0.4 pts</span>down from 2.7%, lower is better</p>
    <svg class="mt-1.5 block h-10 w-full overflow-visible" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="fill-kpi-accent opacity-10" d="M0 3L8.6 8L17.1 8L25.7 13L34.3 13L42.9 18L51.4 18L60 23L68.6 18L77.1 23L85.7 28L94.3 28L102.9 33L111.4 28L120 33L120 36L0 36Z"/><path class="fill-none stroke-kpi-accent stroke-2 [stroke-linecap:round] [stroke-linejoin:round]" vector-effect="non-scaling-stroke" d="M0 3L8.6 8L17.1 8L25.7 13L34.3 13L42.9 18L51.4 18L60 23L68.6 18L77.1 23L85.7 28L94.3 28L102.9 33L111.4 28L120 33"/></svg>
  </article>
  <article class="flex min-w-0 flex-col gap-1.5 rounded-2xl border border-kpi-line bg-white px-[18px] pt-[18px] pb-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <div class="flex items-baseline justify-between gap-2"><h3 class="text-[.84rem] font-semibold text-kpi-muted">Avg. order value</h3><span class="text-[.74rem] whitespace-nowrap text-kpi-muted">Oct 1–15</span></div>
    <p class="text-[1.85rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">$62.40</p>
    <p class="flex flex-wrap items-center gap-2 text-[.8rem] text-kpi-muted"><span class="inline-flex items-center gap-[3px] rounded-full bg-kpi-bad-bg py-0.5 pr-2 pl-1.5 text-[.78rem] font-bold text-kpi-bad tabular-nums"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>−3.2%</span>down from $64.46 in Sep</p>
    <svg class="mt-1.5 block h-10 w-full overflow-visible" viewBox="0 0 120 36" preserveAspectRatio="none" aria-hidden="true"><path class="fill-kpi-accent opacity-10" d="M0 3L8.6 8.4L17.1 4.5L25.7 13L34.3 17.6L42.9 12.2L51.4 21.5L60 19.9L68.6 26.1L77.1 28.4L85.7 23.8L94.3 30.7L102.9 27.6L111.4 33L120 31.5L120 36L0 36Z"/><path class="fill-none stroke-kpi-accent stroke-2 [stroke-linecap:round] [stroke-linejoin:round]" vector-effect="non-scaling-stroke" d="M0 3L8.6 8.4L17.1 4.5L25.7 13L34.3 17.6L42.9 12.2L51.4 21.5L60 19.9L68.6 26.1L77.1 28.4L85.7 23.8L94.3 30.7L102.9 27.6L111.4 33L120 31.5"/></svg>
  </article>
</div></div>

<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#4b5768] uppercase">Compact tiles with icons</span>
<div class="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-4 text-kpi-ink">
  <article class="flex min-w-0 items-center gap-3.5 rounded-2xl border border-kpi-line bg-white p-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <span class="grid size-11 flex-none place-items-center rounded-xl bg-[#e8f1fc] text-[#1f5fae]"><svg class="size-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M19 8v6M22 11h-6"/></svg></span>
    <div class="flex min-w-0 flex-col gap-0.5"><h3 class="text-[.84rem] font-semibold text-kpi-muted">New signups</h3><p class="text-[1.4rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">412</p>
      <p class="inline-flex items-center gap-1 text-[.78rem] font-semibold tabular-nums text-kpi-good"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 18% this week</p></div>
  </article>
  <article class="flex min-w-0 items-center gap-3.5 rounded-2xl border border-kpi-line bg-white p-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <span class="grid size-11 flex-none place-items-center rounded-xl bg-[#e8f1fc] text-[#1f5fae]"><svg class="size-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v3a2 2 0 0 0 0 4v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3a2 2 0 0 0 0-4z"/><path d="M13 5v2M13 11v2M13 17v2"/></svg></span>
    <div class="flex min-w-0 flex-col gap-0.5"><h3 class="text-[.84rem] font-semibold text-kpi-muted">Open tickets</h3><p class="text-[1.4rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">37</p>
      <p class="inline-flex items-center gap-1 text-[.78rem] font-semibold tabular-nums text-kpi-good"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>Down 9 since Monday</p></div>
  </article>
  <article class="flex min-w-0 items-center gap-3.5 rounded-2xl border border-kpi-line bg-white p-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <span class="grid size-11 flex-none place-items-center rounded-xl bg-[#e8f1fc] text-[#1f5fae]"><svg class="size-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg></span>
    <div class="flex min-w-0 flex-col gap-0.5"><h3 class="text-[.84rem] font-semibold text-kpi-muted">First response</h3><p class="text-[1.4rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">1h 42m</p>
      <p class="inline-flex items-center gap-1 text-[.78rem] font-semibold tabular-nums text-kpi-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 12m, slower</p></div>
  </article>
  <article class="flex min-w-0 items-center gap-3.5 rounded-2xl border border-kpi-line bg-white p-4 shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)]">
    <span class="grid size-11 flex-none place-items-center rounded-xl bg-[#e8f1fc] text-[#1f5fae]"><svg class="size-[22px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2l3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.2-6.2 3.2L7 14.2 2 9.3l6.9-1z"/></svg></span>
    <div class="flex min-w-0 flex-col gap-0.5"><h3 class="text-[.84rem] font-semibold text-kpi-muted">Net promoter score</h3><p class="text-[1.4rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums">61</p>
      <p class="inline-flex items-center gap-1 text-[.78rem] font-semibold tabular-nums text-kpi-good"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>Up 4 pts on Q3</p></div>
  </article>
</div></div>

<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#4b5768] uppercase">Hero metric with breakdown</span>
<div class="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-4 text-kpi-ink">
  <article class="col-span-full grid grid-cols-1 gap-x-7 gap-y-[22px] rounded-[18px] border border-kpi-line bg-white p-[22px] shadow-[0_1px_2px_rgba(15,23,42,.04),0_8px_24px_rgba(15,23,42,.05)] sm:grid-cols-[minmax(0,1.1fr)_minmax(0,1fr)]">
    <div class="flex min-w-0 flex-col gap-1.5">
      <div class="flex items-baseline justify-between gap-2"><h3 class="text-[.84rem] font-semibold text-kpi-muted">Monthly recurring revenue</h3><span class="text-[.74rem] whitespace-nowrap text-kpi-muted">October 2026</span></div>
      <p class="text-[2.1rem] leading-[1.15] font-[750] tracking-[-.02em] tabular-nums sm:text-[2.6rem]">$128,940</p>
      <p class="flex flex-wrap items-center gap-2 text-[.8rem] text-kpi-muted"><span class="inline-flex items-center gap-[3px] rounded-full bg-kpi-good-bg py-0.5 pr-2 pl-1.5 text-[.78rem] font-bold text-kpi-good tabular-nums"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>+4.1%</span>up $5,080 from $123,860 in September</p>
    </div>
    <div class="flex flex-col justify-end gap-1.5">
      <svg class="mt-1.5 block h-[90px] w-full overflow-visible" viewBox="0 0 300 72" preserveAspectRatio="none" aria-hidden="true"><path class="fill-kpi-accent opacity-10" d="M0 69L60 56.5L120 46.6L180 33.8L240 16.6L300 3L300 72L0 72Z"/><path class="fill-none stroke-kpi-accent stroke-2 [stroke-linecap:round] [stroke-linejoin:round]" vector-effect="non-scaling-stroke" d="M0 69L60 56.5L120 46.6L180 33.8L240 16.6L300 3"/></svg>
      <p class="flex justify-between text-[.72rem] text-kpi-muted"><span>May $104.2k</span><span>Oct $128.9k</span></p>
    </div>
    <ul class="col-span-full grid grid-cols-2 gap-3 border-t border-kpi-line pt-4 sm:grid-cols-4" aria-label="MRR movement in October">
      <li class="flex flex-col gap-0.5 text-[.8rem] text-kpi-muted">New business<strong class="text-[1.05rem] text-kpi-ink tabular-nums">+$9,820</strong></li>
      <li class="flex flex-col gap-0.5 text-[.8rem] text-kpi-muted">Expansion<strong class="text-[1.05rem] text-kpi-ink tabular-nums">+$3,410</strong></li>
      <li class="flex flex-col gap-0.5 text-[.8rem] text-kpi-muted">Contraction<strong class="text-[1.05rem] text-kpi-ink tabular-nums">−$1,620</strong></li>
      <li class="flex flex-col gap-0.5 text-[.8rem] text-kpi-muted">Churned<strong class="text-[1.05rem] text-kpi-ink tabular-nums">−$6,530</strong></li>
    </ul>
  </article>
</div></div>
CSS
@theme {
  --color-kpi-ink: #0f172a;
  --color-kpi-muted: #4b5768;
  --color-kpi-line: #e2e8f0;
  --color-kpi-accent: #2a78d6;
  --color-kpi-good: #15803d;
  --color-kpi-good-bg: #dcfce7;
  --color-kpi-bad: #b91c1c;
  --color-kpi-bad-bg: #fee2e2;
}

About this set

Three ways to show the numbers a dashboard opens with. KPI cards with sparklines is a row of four cards for net revenue, active subscribers, monthly churn and average order value: each has a label, the period, a large value, a delta pill and a small area sparkline that stretches to the card width. Compact tiles with icons packs four smaller stats (new signups, open tickets, first response time, NPS) next to an icon square, with a one-line trend. Hero metric with breakdown gives monthly recurring revenue a full-width card with a larger chart and a four-way split into new business, expansion, contraction and churn. Use the cards for a top row, the tiles where space is tight and the hero card for the one number the page is about. Direction is never carried by colour alone: every delta has a signed number, an arrow and words such as up from, down from or lower is better, so a falling churn rate reads as good news. The sparklines are inline SVG paths with a non-scaling stroke, marked aria-hidden because the text beside them already says what they show. No JavaScript.

What’s included

  • Four KPI cards with signed deltas and area sparklines
  • Compact icon tiles for dense dashboard rows
  • Full-width hero metric with a four-way MRR breakdown
  • Up and down shown by sign, arrow and wording, not colour alone
  • Inline SVG sparklines that stretch to any card width
  • Tabular figures so values line up

Accessibility

Each card has a heading for its label, and the value, delta and comparison are plain text in reading order. Good and bad changes use a signed number, an arrow and words, so they do not depend on red and green. Sparklines and icons are decorative and hidden from screen readers. Text and badges meet WCAG AA contrast.

Customise it

Change --kpi-accent for the sparklines and --kpi-good, --kpi-bad and their -bg partners for the delta pills on .kpi-set. In Bootstrap the same colours are Bootstrap variables such as --bs-success-text-emphasis set on .kpi-set; in Tailwind edit the kpi colours in the @theme block.