Skip to content

ExpressiveCSS

Browse documentation

KPI

One key figure in a card, with a trend chip, a sparkline and details.

View as Markdown

Use an <article class="kpi"> card to show one headline figure. It holds a label, the value, a trend chip, a sparkline and a line of context.

Put the label and value in a <dl> so a screen reader reads them as a pair. The article is a card, so filled and outlined work as they do on cards. KPIs in a grid row stretch to the same height and line up their footers. The KPI itself is CSS only. The chart component draws the chart with its own script.

Revenue
$48,200
+12.5%
Revenue over 10 days, in thousands
DayRevenue
Day 140.1
Day 242.3
Day 341
Day 443.8
Day 544.6
Day 643.9
Day 745.7
Day 846.2
Day 945.8
Day 1048.2
Churn
3.1%
+0.4 pts
Churn over 10 days, in percent
DayChurn
Day 12.4%
Day 22.5%
Day 32.6%
Day 42.5%
Day 52.8%
Day 62.9%
Day 72.9%
Day 83%
Day 93.1%
Day 103.1%
Orders
410
+32%
Orders over 10 days
DayOrders
Day 1310
Day 2290
Day 3335
Day 4320
Day 5360
Day 6340
Day 7380
Day 8372
Day 9395
Day 10410
<article class="kpi outlined">
  <dl>
    <dt>
      <span class="kpi-icon material-symbols-outlined" aria-hidden="true">payments</span>
      Revenue
    </dt>
    <dd class="kpi-value">$48,200</dd>
    <dd class="kpi-trend up">+12.5%</dd>
  </dl>
  <button type="button" class="icon-button kpi-actions" aria-label="Revenue options">
    <span class="material-symbols-outlined" aria-hidden="true">more_vert</span>
  </button>
  <figure class="line-chart sparkline area">
    <figcaption class="visually-hidden">Revenue over 10 days, in thousands</figcaption>
    <table>
      <thead><tr><th>Day</th><th>Revenue</th></tr></thead>
      <tbody>
        <tr><th>Day 1</th><td>40.1</td></tr>
        <!-- … -->
      </tbody>
    </table>
  </figure>
  <div class="kpi-footer">Compared with $42,800 last month</div>
</article>

Trend

Add a <dd class="kpi-trend"> chip to compare the value with an earlier one. up and down add an arrow. negative marks bad news in the error container colors, whichever way the number moved. It also turns the first series of a line, column, bar or mixed chart in the same KPI to the error color. The arrow is decoration, so the text has to give the direction, as in +0.4 pts.

<dd class="kpi-trend up negative">+0.4 pts</dd>

Optional parts

Everything after the <dl> is optional and stacks in source order.

  • .kpi-icon goes inside the <dt> and draws a tonal icon box. Hide the icon with aria-hidden="true".
  • .kpi-actions on a button or menu trigger places it in the top corner. Name it after the figure, as in aria-label="Revenue options".
  • A sparkline chart from any chart component. Set its height with the chart's own token, such as --md-comp-line-chart-height.
  • A <progress class="progress"> shows progress toward a goal. Name it with aria-label.
  • A <p> adds supporting text.
  • .kpi-footer closes the card under a divider, with details or a link.
Quarterly goal
72%
−3% this week

$720k of $1M booked, with 18 days left.

<article class="kpi filled">
  <dl>
    <dt>Quarterly goal</dt>
    <dd class="kpi-value">72%</dd>
    <dd class="kpi-trend down">−3% this week</dd>
  </dl>
  <progress class="progress" value="72" max="100" aria-label="Quarterly goal"></progress>
  <p>$720k of $1M booked, with 18 days left.</p>
</article>

For several figures without charts or actions, use a row of stat tiles instead. They are lighter.

Accessibility

The <dt> and <dd> pairing names the value. Without it, a screen reader reads a bare number. A sparkline is not focusable and has no tooltip. Its table stays in the page, so give it a caption that names the measure and period. Write the trend's direction and unit in its text, because screen readers don't announce the arrow or the error colors.

Tokens

Override these on the .kpi. Container color, shape and padding come from the card tokens.

Token Default
--md-comp-kpi-icon-container-color--md-sys-color-primary-container
--md-comp-kpi-icon-color--md-sys-color-on-primary-container
--md-comp-kpi-trend-container-color--md-sys-color-secondary-container
--md-comp-kpi-trend-color--md-sys-color-on-secondary-container

No matching pages

  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.

    Default source: Mist Iris.

    ExpressiveCSS presets: Lagoon, Harbor, Breeze, Cobalt, Iris.

    Bold

    Soft

    Mist

    Glow