Skip to content

ExpressiveCSS

Browse documentation

Mixed chart

Columns, lines and areas together from one data table, with a second scale for values in other units.

View as Markdown

Wrap a <table> in a <figure class="mixed-chart"> to draw it as columns, lines and areas on one plot. The class on each series header picks how that series is drawn.

The markup is the same as for a line chart. Give a header cell column to draw that series as columns from zero, or area for a line with a fading fill under it. Any other series is a line, and dashed dashes it. Columns sit behind the lines.

A legend names the series. A tooltip follows the pointer or the arrow keys from row to row, with a point on each line. Add toggle to the figure to make each legend item a button that shows or hides its series, as on the line chart.

Revenue against target, $K
MonthRevenueTarget
Jan$62$65
Feb$71$65
Mar$68$70
Apr$80$70
May$76$75
Jun$89$75
<figure class="mixed-chart">
  <figcaption>Revenue against target, $K</figcaption>
  <table>
    <thead>
      <tr><th>Month</th><th class="column">Revenue</th><th class="dashed">Target</th></tr>
    </thead>
    <tbody>
      <tr><th>Jan</th><td>$62</td><td>$65</td></tr>
      <tr><th>Feb</th><td>$71</td><td>$65</td></tr>
      <!-- … -->
    </tbody>
  </table>
</figure>

Second scale

Add end to a series header to draw that series against a second scale. The second scale fits that series' own values, so a series in other units or of another size still fills the plot. Without end, series share one scale. To fix the second scale, set data-end-min and data-end-max on the figure, as data-min and data-max fix the first.

Add axis to label both scales at round values. The first scale's labels sit beside the plot's start, with a grid line at each. The second scale's labels run along its end. When neither scale has a fixed end, the second scale stretches to as many steps as the first, so its labels share the same grid lines. The labels repeat each scale's currency or percent sign and are hidden from assistive technology. Without axis, name both units in the caption or the headers.

Ad spend ($K) and conversions
MonthSpendConversions
Jan$12340
Feb$15410
Mar$14390
Apr$18480
May$20520
Jun$22610
<figure class="mixed-chart axis">
  <figcaption>Ad spend ($K) and conversions</figcaption>
  <table>
    <thead>
      <tr><th>Month</th><th class="column">Spend</th><th class="end">Conversions</th></tr>
    </thead>
    <tbody>
      <tr><th>Jan</th><td>$12</td><td>340</td></tr>
      <!-- … -->
    </tbody>
  </table>
</figure>

Areas

An area series fills down to the bottom of the plot. In this example, traffic is an area and the bounce rate is a dashed line on a second scale from 0% to 100%.

Traffic (thousands of visits) and bounce rate
MonthTrafficBounce rate
Jan8.258%
Feb9.455%
Mar10.152%
Apr9.854%
May11.649%
Jun12.446%
<figure class="mixed-chart" data-end-min="0" data-end-max="100">
  <figcaption>Traffic (thousands of visits) and bounce rate</figcaption>
  <table>
    <thead>
      <tr><th>Month</th><th class="area">Traffic</th><th class="dashed end">Bounce rate</th></tr>
    </thead>
    <tbody>
      <tr><th>Jan</th><td>8.2</td><td>58%</td></tr>
      <!-- … -->
    </tbody>
  </table>
</figure>

All three kinds fit on one plot. Several series can share the second scale. Here the margin and the growth rate are both percentages from 0 to 35, and revenue keeps the first scale.

Revenue ($K), profit margin and customer growth
MonthRevenueProfit marginCustomer growth
Jan$42018%4%
Feb$46019%5%
Mar$51021%6%
Apr$48020%5%
May$56022%7%
Jun$61024%8%
Jul$59023%7%
Aug$64025%9%
Sep$70027%10%
Oct$68026%9%
Nov$75028%11%
Dec$82030%13%
<figure class="mixed-chart" data-end-min="0" data-end-max="35">
  <figcaption>Revenue ($K), profit margin and customer growth</figcaption>
  <table>
    <thead>
      <tr>
        <th>Month</th>
        <th class="column">Revenue</th>
        <th class="area end">Profit margin</th>
        <th class="dashed end">Customer growth</th>
      </tr>
    </thead>
    <tbody>
      <tr><th>Jan</th><td>$420</td><td>18%</td><td>4%</td></tr>
      <!-- … -->
    </tbody>
  </table>
</figure>

Stacked columns

Add stacked to stack the column series into one column per row, so a reader sees both the parts and the total. Lines and areas keep their own values, such as a target to compare the totals with. Columns on the second scale stack in their own column beside the first. List them after the others. points marks each value on the lines with a dot, and straight draws straight lines between them instead of a curve.

Revenue by channel ($K) against target
MonthOnlineStoreTarget
Jan382465
Feb442765
Mar412770
Apr522870
May492775
Jun583175
<figure class="mixed-chart axis stacked points straight">
  <figcaption>Revenue by channel ($K) against target</figcaption>
  <table>
    <thead>
      <tr><th>Month</th><th class="column">Online</th><th class="column">Store</th><th class="dashed">Target</th></tr>
    </thead>
    <tbody>
      <tr><th>Jan</th><td>38</td><td>24</td><td>65</td></tr>
      <!-- … -->
    </tbody>
  </table>
</figure>

Chart cards

Put a chart in a card with the figures it explains. The card adds no chart styles. Set the plot's height with --md-comp-mixed-chart-height.

Support tickets
190
Resolved in 3.9h on average
Tickets and resolution time by month
MonthTicketsHours to resolve
Jan1425.2
Feb1584.8
Mar1305.5
Apr1754.3
May1604.6
Jun1903.9
<article class="outlined">
  <div class="p-4">
    <dl class="stats my-0">
      <div>
        <dt>Support tickets</dt>
        <dd>190</dd>
        <dd class="stat-change up">Resolved in 3.9h on average</dd>
      </div>
    </dl>
    <figure class="mixed-chart" style="--md-comp-mixed-chart-height: 120px">
      <figcaption class="visually-hidden">Tickets and resolution time by month</figcaption>
      <table><!-- … --></table>
    </figure>
  </div>
</article>

For a trend beside a figure that already explains it, add sparkline. It draws a 48px chart with no grid, labels, legend or tooltip.

Values and colors

The chart reads cells as a line chart does. A cell's number is its data-value, or its text without currency signs, percent signs or grouping commas. The tooltip shows each cell's text as written. A scale with columns always includes zero. Otherwise it spans its values with a tenth to spare at each end. The data attributes or the min and max options override that range. A gap breaks a line and leaves a column's slot empty.

Series take primary, tertiary, secondary and on-surface-variant in column order, whatever their kind. A fifth series repeats the first color.

Accessibility

The table is the chart's text alternative. Give it a header row and a header cell per row, and name the chart with a <figcaption>. There is no y axis, so put the units in the caption, the headers or the cells. The chart hides its drawn marks, labels and legend from assistive technology.

The plot is one Tab stop, named by the caption. Left and right move between rows. Home and End jump to the ends, and Escape hides the tooltip. In a right-to-left page, the rows and the arrows run right to left. On a touch screen, tap a row to show it. The tooltip is a polite live region, so a screen reader announces each row's values as the tooltip moves. A sparkline is not focusable.

Readers can tell dashed lines from solid ones without color. In forced colors, the marks keep their colors so the legend still matches them.

JavaScript

AutoInit() starts every .mixed-chart. To start one yourself, call MixedChart.init. After you change its table, call update() to redraw it in place. Or put data-watch on the figure, and the chart redraws itself. The columns, lines and areas move from their old values to the new ones, as in the line and column charts. With reduced motion, they appear at once. The mixed chart has the line chart's methods and options. min and max apply to the first scale.

const chart = Expressive.MixedChart.init(document.querySelector('.mixed-chart'));
chart.show(2);   // highlight the third row; -1 hides the tooltip
chart.update();  // redraw from the table; focus and the highlighted row stay
chart.destroy(); // remove the drawing and show the table again

Tokens

Override these on the .mixed-chart.

Token Default
--md-comp-mixed-chart-height240px, the plot's height; 48px for a sparkline
--md-comp-mixed-chart-column-width50% of each row's width
--md-comp-mixed-chart-shape4px, a column's end radius
--md-comp-mixed-chart-line-width3px; 2px for a sparkline
--md-comp-mixed-chart-grid-coloroutline-variant
--md-comp-mixed-chart-axis-width48px, the room on each side of the plot for axis labels
--md-comp-mixed-chart-color-1 … -4primary, tertiary, secondary, on-surface-variant

For a selective Sass build, include "mixed-chart" in $components.

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