Skip to content

ExpressiveCSS

Browse documentation

Scatter chart

One measure plotted against another, with a point for each row.

View as Markdown

A <figure class="scatter-chart"> plots one measure against another from a <table>, with a point for each row.

The first column labels each row and the second holds its x value. Each further column is a series of y values, named by its header cell. Each row draws one point per series, so a scatter chart shows how two measures move together, such as a car's weight and its fuel economy. To show one measure over time, use a line chart.

Ad spend and signups by channel
ChannelSpendSignups
Search$12,000340
Social$8,000150
Video$15,000210
Email$2,000120
Display$6,00060
Podcasts$4,00070
<figure class="scatter-chart axis">
  <figcaption>Ad spend and signups by channel</figcaption>
  <table>
    <thead>
      <tr><th>Channel</th><th>Spend</th><th>Signups</th></tr>
    </thead>
    <tbody>
      <tr><th>Search</th><td>$12,000</td><td>340</td></tr>
      <tr><th>Social</th><td>$8,000</td><td>150</td></tr>
      <!-- One row per channel -->
    </tbody>
  </table>
</figure>

Several series

Each further column is another series, in the next color, with a legend below the chart. Add toggle to the figure to make each legend item a button that shows or hides its series, as on the line chart. Both scales refit to the points left.

Series share the x column. A series that needs other x values puts them in rows of their own, with the other series' cells left empty.

Fuel economy by weight (mpg)
CarWeight (kg)CityHighway
Civic13003140
Corolla14003241
Prius14505756
Camry16002839
RAV416502735
F-15022002024
Tahoe26001520
<figure class="scatter-chart axis toggle">
  <figcaption>Fuel economy by weight (mpg)</figcaption>
  <table>
    <thead>
      <tr><th>Car</th><th>Weight (kg)</th><th>City</th><th>Highway</th></tr>
    </thead>
    <tbody>
      <tr><th>Civic</th><td>1300</td><td>31</td><td>40</td></tr>
      <!-- One row per car -->
    </tbody>
  </table>
</figure>

Bubble sizes

Add bubble to the figure to size each point by a third measure. The last column holds the sizes. It is no series: every point in its row becomes a bubble whose area follows the row's size. The largest size drawn is --md-comp-scatter-chart-bubble-size across, 48px by default, and the rest scale by area against it. A row whose size is not a positive number draws no points.

The tooltip adds the size column's header and cell, and the marker outlines the highlighted bubble. Bubbles are partly transparent, and smaller ones are drawn over larger ones in each series, so overlaps stay readable. The chart leaves half the largest diameter of room around the plot, so a bubble at the end of a scale stays clear of the axis labels, caption and legend. A toggle legend refits the sizes to the bubbles left, and after update() each bubble grows or shrinks from its old size.

Ad spend, signups and visits by channel
ChannelSpendSignupsVisits
Search$12,0003409,000
Social$8,00015014,000
Video$15,00021022,000
Email$2,0001203,000
Display$6,0006011,000
Podcasts$4,000702,500
<figure class="scatter-chart axis bubble">
  <figcaption>Ad spend, signups and visits by channel</figcaption>
  <table>
    <thead>
      <tr><th>Channel</th><th>Spend</th><th>Signups</th><th>Visits</th></tr>
    </thead>
    <tbody>
      <tr><th>Search</th><td>$12,000</td><td>340</td><td>9,000</td></tr>
      <!-- One row per channel; the last column sizes its bubble -->
    </tbody>
  </table>
</figure>

Values and scale

Cells read as in a line chart. A cell's number is its data-value, or its text without currency signs, percent signs or grouping commas. The tooltip shows the cell's text as written. A row whose x cell is not a number draws no points, and a y cell that is not a number draws no point for its series.

Both scales run from a little below the lowest value to a little above the highest. Set data-x-min and data-x-max on the figure to fix the x scale, and data-min and data-max to fix the y scale. x grows toward the inline end, so it runs leftward in a right-to-left page.

Add axis to label both scales at round values, with a grid line at each: y beside the plot and x below it. Each scale's labels repeat its cells' currency or percent sign. The labels are hidden from assistive technology. The table still carries the values.

<figure class="scatter-chart axis" data-x-min="0" data-min="0">
  <figcaption>Ad spend and signups by channel</figcaption>
  <table><!-- … --></table>
</figure>

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>. The drawn chart, labels and legend are hidden from assistive technology.

The plot is one Tab stop named by the caption. Keyboard focus shows the first point. The arrow keys step through the points in table order: right and down go to the next point, left and up to the one before. Within a row the series go in column order. Home and End jump to the first and last points, and Escape hides the tooltip. The arrows keep this meaning in a right-to-left page, since table order is not a direction on screen. The pointer shows the point nearest to it. The tooltip is a polite live region, so a screen reader hears the row, its x value and the series value as it moves. In forced colors the points keep their colors so the legend still keys them.

JavaScript

AutoInit() starts every .scatter-chart. To start one yourself, call ScatterChart.init. After changing its table, call update() to redraw it in place, or put data-watch on the figure and it redraws itself. Points move from their old places to the new ones, or appear at once with reduced motion. It has the line chart's options and methods, plus xMin and xMax for the x scale.

const chart = Expressive.ScatterChart.init(document.querySelector('.scatter-chart'), { xMin: 0 });
chart.show(2);   // highlight the third point in table order; -1 hides the tooltip
chart.update();  // redraw from the table; focus and the highlighted point stay
chart.destroy(); // remove the drawing and show the table again

Tokens

Override these on the .scatter-chart.

Token Default
--md-comp-scatter-chart-height240px
--md-comp-scatter-chart-point-size8px
--md-comp-scatter-chart-bubble-size48px, the largest bubble diameter
--md-comp-scatter-chart-grid-coloroutline-variant
--md-comp-scatter-chart-axis-width48px, room for the y axis labels
--md-comp-scatter-chart-color-1 … -4primary, tertiary, secondary, on-surface-variant

For a selective Sass build, include "scatter-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