motion-sparkline
A small trend line that fits inside a sentence, a table cell or a stat tile. It draws itself in when it scrolls into view, and springs to new values when the data changes. It takes the text color, so it matches the text around it.
Preview
Signups this week
Response time
<p>Signups this week <motion-sparkline values="3, 5, 4, 8, 7, 11"></motion-sparkline> are up 38%.</p>Quick start
Save this as index.html and open it in a browser. No install, no build step.
<!doctype html>
<html>
<head>
<script type="module" src="https://cdn.jsdelivr.net/npm/motion-components@1/dist/motion-sparkline.js/+esm"></script>
</head>
<body>
<p>Signups this week <motion-sparkline values="3, 5, 4, 8, 7, 11"></motion-sparkline></p>
</body>
</html>In a project with a bundler, install the package and import the component once:
npm install motion-componentsimport 'motion-components/motion-sparkline'In a table
Put a sparkline in a table cell to show the trend next to the latest value.
| Product | Sales | Last 8 weeks |
|---|---|---|
| Starter | 1,240 | |
| Pro | 860 | |
| Team | 310 |
<td>
<motion-sparkline values="5, 7, 6, 8, 9, 11, 10, 14"></motion-sparkline>
</td>Stat tile
Combine it with motion-counter for a number that counts up above its trend. area adds a light wash under the line.
<div class="stat">
<span class="stat-label">Revenue</span>
<motion-counter to="48.2" decimals="1" duration="1.4" prefix="€" suffix="K"></motion-counter>
<motion-sparkline values="31, 35, 33, 38, 41, 39, 45, 48" area></motion-sparkline>
</div>.stat {
display: grid;
gap: 0.25rem;
font-size: 2rem;
font-weight: 700;
}
.stat-label {
font-size: 0.85rem;
font-weight: 500;
}
.stat motion-sparkline {
--mc-sparkline-width: 100%;
--mc-sparkline-height: 2.5rem;
}Live data
Change values and the line springs to the new shape. From JavaScript you can also set data to an array of numbers, such as spark.data = [12, 14, 13]. It takes precedence over values.
Active users
<motion-sparkline id="users" values="12, 14, 13, 15, 17, 16, 18, 20"></motion-sparkline>
<script type="module">
const spark = document.querySelector('#users')
setInterval(() => {
const values = spark.values.split(',').map(Number)
const next = Math.max(0, values.at(-1) + Math.round(Math.random() * 6 - 3))
spark.values = [...values.slice(1), next].join(', ')
}, 1500)
</script>More patterns, such as a period switcher, a chart from a form and data from a JSON file, are on the Chart Recipes page.
Properties
| Attribute | Property | Type | Default | Description |
|---|---|---|---|---|
| | | string | '' | Comma-separated numbers. At least two |
| | | number[] | null | Property only: the numbers as an array, set from JavaScript. Takes precedence over |
| | | boolean | false | Fills the area under the line with a light wash |
| | | string | '' | Accessible name. Without it, the name describes the trend |
| | | string | 'view' | When the draw-in runs: |
| | | number | 1 | Spring duration in seconds |
| | | number | 0.2 | Spring bounciness when the values change |
CSS custom properties
| Property | Type | Default | Description |
|---|---|---|---|
| | length | 6em | Width |
| | length | 1.5em | Height |
| | color | currentColor | Line color |
| | color | line color | Color of the dot on the last value |
JavaScript API
replay() draws the line in again. It also has play(), pause(), finish(), cancel() and playState. See the JavaScript API.
Accessibility
The sparkline has role="img" and a name that describes the trend, for example "from 3 to 11, low 3, high 11". Set
label to give it your own name. With prefers-reduced-motion, the line shows at once and changes without animation.