Core · Show content
Meter
Draws a value in a known range as a bar, next to its figure, with the native meter element.
Example
A table of delivery routes, each with a meter that shows its parcels out of 1,500.
| Route | Parcels |
|---|---|
| Sevilla to Madrid | 1,204 |
| Cádiz to Málaga | 312 |
| Huelva to Faro | 58 |
Known issues
None known.
Code
Copy the markup
A bare meter needs no class: it has the size of the component and the colors of the browser.
<label for="storage">Storage used, 6 of 10 GB</label>
<meter id="storage" value="6" min="0" max="10">6 of 10 GB</meter>
.luz-meter draws the bar and its track in the brand color.
A bar in the cell of its figure, in a table. The figure is text, so the bar is a picture of it and is hidden from assistive technology:
<table class="luz-table">
<caption>Parcels per route</caption>
<thead>
<tr><th scope="col">Route</th><th scope="col" class="luz-table__numeric">Parcels</th></tr>
</thead>
<tbody>
<tr>
<td data-label="Route">Sevilla to Madrid</td>
<td class="luz-table__numeric" data-label="Parcels">1,204<meter class="luz-meter" value="1204" min="0" max="1500" aria-hidden="true">1,204 of 1,500</meter></td>
</tr>
<tr>
<td data-label="Route">Cádiz to Málaga</td>
<td class="luz-table__numeric" data-label="Parcels">312<meter class="luz-meter" value="312" min="0" max="1500" aria-hidden="true">312 of 1,500</meter></td>
</tr>
</tbody>
</table>
A bar on its own, with a visible name and the figure in it:
<label for="storage">Storage used, 6 of 10 GB</label>
<meter class="luz-meter" id="storage" value="6" min="0" max="10">6 of 10 GB</meter>
Variants and options
One class. The bar comes from the native attributes.
| Attribute | Effect |
|---|---|
value, min and max | The value and its range: min is 0 and max is 1 if you leave them out. A value outside the range is clamped to it |
aria-hidden="true" | For a bar next to its figure: the figure is read, the picture is not |
low, high, optimum | Do not set them: they would only change the colour the browser chooses, and every state is drawn in the brand colour |
How it works
The native <meter> element, styled by components/meter.css: an 8 px bar, full width of its box and at least 8rem long, with the brand colour as the fill and a 1 px edge in the field border colour, so the whole length shows on any surface.
- The browser draws the fill as
valuebetweenminandmax. - Every state is the same colour. The figure and the scale say what the value means, not a green or a red: status colours keep their own meanings (alerts, tags).
- Use the same
maxin every row of a table, or the bars lie. - In forced colors the bar keeps a border and draws the fill in the system highlight colour.
- The text inside the element is the fallback for a browser that does not draw it. Say the figure there too.
Without JavaScript
The bar shows the value in the markup. Moving it needs your script, which sets value.
Keyboard and ARIA
A meter is not interactive and takes no focus.
- Next to its figure, in the same cell or the same line, hide the bar with
aria-hidden="true": the figure is text, and the table is the accessible chart. A reader hears the figure once. - Put the bar in the cell of its figure, not in a column of its own: a column of bars would read as a column of empty cells. If you do want a column for the bar, each cell carries visible text of its own, such as “80 %”, under a heading that says what it is.
- A meter that is not hidden needs a name: a
<label for>oraria-labelledby. It is then read as “value, minimum, maximum”, so it repeats a figure that is already there: hide it unless it stands alone. - The bar is a picture of the figure in the same cell: assistive technology reads the figure.
Contrast and focus are in the Design tab.
Design
When to use
Use a meter for a value in a known range, next to its figure, in a few to a few dozen rows that share a scale: a share of a total, a count against a quota.
When not to use
Do not use a meter for a task that is running: use progress.
- For a trend over time, use a chart library; keep the table as its text alternative. LUZ draws no line, area or pie chart.
- When exact values matter more than the shape, leave the bar out: the figure is already there.
- Do not use the bar's colour to say good or bad: it is always the brand colour.
Do and don't
Writing the content
The figure is the content; the bar only shows how it compares.
- Put the figure in text in the same cell or line, with its unit in the column heading: “Parcels”.
- Say the scale in the caption or the heading when it is not obvious: “Parcels per route, this week”.
- Inside the element, write the figure and its range as a fallback: “1,204 of 1,500”.
Contrast and focus
The fill is the brand colour on a muted track. The track has an edge in the field border colour, so you can see where the bar ends.
| Part | Colour on background | Light | Dark | High contrast | Needs |
|---|---|---|---|---|---|
Fill against the track | --luz-brand-primary on --luz-surface-muted | 5.6:1 | 7.7:1 | 13.5:1 | 3:1 |
Edge of the track against the page | --luz-input-border on --luz-surface-page | 3.7:1 | 4.2:1 | 21.0:1 | 3:1 |
Edge of the track against a card | --luz-input-border on --luz-surface | 3.9:1 | 3.9:1 | 21.0:1 | 3:1 |
Measured from the token values of each mode, rounded down. Needs is the WCAG 2.2 AA minimum: 4.5:1 for text, 3:1 for focus rings, borders and icons.
- Focus: the bar takes none.
- Not colour alone: the figure is text beside the bar, so the value never depends on telling the two parts of the bar apart.
Tokens it uses
The 4 tokens that components/meter.css reads, by family. Each family links to its page, with the values in every mode. In Figma they are variables with the same names: see Tokens in Figma.
- Radius
--luz-radius-sm
Keyboard and ARIA are in the Code tab.