Naming Charts and Figures with figcaption

Permalink to "Naming Charts and Figures with figcaption"

A chart without a name is announced as “graphic” or not at all. A chart named “Chart 1” is barely better. Charts need a short name that says what they show (“Monthly revenue, 2025”) and a caption that says what matters (“Revenue rose 18% after the March launch”). HTML gives you figure and figcaption for exactly this, and SVG charts can point aria-labelledby at the visible title. Getting the combination right avoids both silence and the common double announcement.

This guide belongs to accessible names and descriptions for data widgets.

Spec reference

Permalink to "Spec reference"
  • HTML figure / figcaption — figcaption provides the accessible name of figure when no other name is set.
  • SC 1.1.1 Non-text Content (A) — charts need text alternatives that identify them and convey the key information.
  • SC 1.3.1 (A) — caption programmatically associated with its chart.
  • ARIA — role="img" on an SVG with aria-labelledby or aria-label; aria-describedby for a longer description.
Name and description of a chart figure Tree: the figure element is named by its figcaption; inside, the SVG with role img is named by its title and described by a summary paragraph; a link points to the data table. Name and description of a chart figurefigure (name: figcaption)figcaption: "Monthly revenue, 2025 — up 18% after March launch"svg role="img"aria-labelledby → chart title "Monthly revenue, 2025"aria-describedby → summary paragrapha href="#rev-table": "Revenue data table"
One short name, one takeaway, one route to the data.

When to use — and when not to

Permalink to "When to use — and when not to"

Use figure and figcaption for every chart that sits in content: reports, dashboards, articles. On dense dashboards, a visible heading per widget can replace figcaption, with the chart named by that heading.

Do not repeat the same text in the figure name, the SVG name and an aria-label; screen readers will read it two or three times. The misapplication: alt-style text on the SVG that lists every data point, making a forty-second announcement users cannot skip.

Names that fail versus names that work Comparison: missing names, generic names and data dumps fail users; a short specific name plus a takeaway caption and a link to data works. Names that fail versus names that work✗ "graphic" or silence"Chart 1"Every data point in the nameName read three times✓ "Monthly revenue, 2025, image"Specific subject and periodTakeaway in caption, data in tableOne name per element

Annotated code example

Permalink to "Annotated code example"
<figure aria-labelledby="rev-cap">
  <svg role="img" aria-labelledby="rev-title" aria-describedby="rev-sum" viewBox="0 0 640 320">
    <title id="rev-title">Monthly revenue, 2025</title>              <!-- short name -->
    …bars…
  </svg>
  <figcaption id="rev-cap">
    <strong>Monthly revenue, 2025.</strong>
    <span id="rev-sum">Revenue rose 18% after the March launch and peaked in October.</span>  <!-- takeaway -->
    <a href="#rev-table">View the data table</a>
  </figcaption>
</figure>
<!-- Canvas chart: name the canvas, describe via caption -->
<figure>
  <canvas role="img" aria-label="Monthly revenue, 2025" aria-describedby="rev-sum2"></canvas>
  <figcaption id="rev-sum2">Revenue rose 18% after the March launch.</figcaption>
</figure>

Keyboard & AT behaviour

Permalink to "Keyboard & AT behaviour"
Screen reader On the figure On the SVG
NVDA + Firefox “figure, Monthly revenue, 2025 …” “Monthly revenue, 2025, graphic” + description
JAWS + Chrome “figure” + caption “graphic, Monthly revenue, 2025”
VoiceOver + Safari “Monthly revenue, 2025, figure” “image” + name
Graphics navigation (G) Jumps to the SVG Name read
Naming techniques for chart types Matrix of chart implementations — SVG, canvas, image file, HTML/CSS bars — against the naming technique, where the takeaway goes and how detail is reached. Naming techniques for chart typesNameTakeawayDetailSVG charttitle + aria-labelledbyaria-describedbyData table linkCanvas chartaria-label on canvasfigcaptionData table linkImage filealtfigcaptionData table linkHTML/CSS barsHeading or figurefigcaptionNative table
Every chart type gets a name, a takeaway and a data route.

Step-by-step implementation

Permalink to "Step-by-step implementation"
  1. Write the name first. Subject, measure and period: “Monthly revenue, 2025”. Avoid “chart of” — screen readers already say graphic or image.
  2. Write the takeaway. One or two sentences: the trend, the comparison or the outlier that the chart exists to show.
  3. Wire up references. Give the SVG role="img", aria-labelledby pointing at its title, and aria-describedby pointing at the takeaway. Hide decorative inner elements with aria-hidden if they would otherwise be read.
  4. Add the route to data. Link to a data table on the same page, or a toggle that shows it.
  5. Check for duplicates. Listen to the figure in two screen readers. If the name is read twice, remove the figure’s explicit label and let figcaption name it, or vice versa.

Integration context

Permalink to "Integration context"

Writing the takeaway is covered in writing chart summaries and key takeaways, and longer descriptions in long descriptions for complex charts. Grid naming follows labelling grids with aria-labelledby. Chart library defaults are compared in chart library accessibility.

Gotchas

Permalink to "Gotchas"

SVG title tooltips. A <title> element shows as a tooltip on hover in some browsers; that is usually acceptable, but if not, use aria-label instead.

Interactive charts. If the chart has focusable data points, role="img" hides them; use role="group" or role="application" with a name instead.

Figure without caption. A figure with no figcaption and no label is announced as an unnamed figure; always name it.

Edge cases

Permalink to "Edge cases"
  • Small multiples. Name the group figure (“Revenue by region”) and each small chart (“North”).
  • Live charts. If the takeaway changes with data, update the description text, but do not announce it on every update.
  • Charts in tables. Sparklines in cells need short names such as “Trend: rising” and nothing more.

Worked example

Permalink to "Worked example"

A quarterly report site embedded twenty SVG charts with no names. NVDA users heard “graphic” twenty times, and some charts read out every axis tick. The team wrapped each in a figure with a caption containing a short name and a one-sentence takeaway, added role="img" with aria-labelledby and aria-describedby, hid tick labels from assistive technology and linked each chart to its data table. Reviewers using screen readers could now skim the report by graphics.

Common mistakes

Permalink to "Common mistakes"
  • No name, or “Chart 1”.
  • Data points in the name.
  • Names duplicated across figure and SVG.
  • No route to the underlying data.

Testing checklist

Permalink to "Testing checklist"

Testing it with a screen reader

Permalink to "Testing it with a screen reader"

With NVDA in browse mode, press G to move through graphics and listen to each chart’s name; each should be specific and read once. Press Down Arrow to hear the description and confirm the data table link follows. In JAWS, list graphics with Insert+Ctrl+G and check that names are unique. In VoiceOver, use the rotor’s images list. Then open the accessibility tree in browser developer tools and verify the computed name and description of each SVG match what you intended.

Design system notes

Permalink to "Design system notes"

Make the chart component require title and summary props, render the figure structure automatically and fail a lint check when either is missing.

Writing names for dashboards

Permalink to "Writing names for dashboards"

Dashboards multiply the naming problem: twelve widgets, each with a chart, a title bar and sometimes a menu. Decide on one naming source per widget. The usual choice is the widget’s visible heading, which names the region (with aria-labelledby on the widget container) and the chart inside it. The chart’s own name can then be shorter (“Trend”) because the region supplies context, or it can repeat the heading when charts are reachable on their own through graphics navigation. Avoid timestamps and filter descriptions in names; they change and make every announcement longer. Put them in the description or in visible text near the chart. Finally, keep names stable when data refreshes, so users who return to a widget recognise it by the same words.

FAQ

Permalink to "FAQ"
Should I use figcaption or aria-label?

Prefer visible figcaption; it helps everyone. Use aria-label only when no visible caption fits.

Is the SVG title element enough?

Combined with role img and aria-labelledby, it is reliable; alone, support varies.

How long should the name be?

A few words. Put detail in the description.

Should the caption repeat the heading?

No. If a heading names the chart, let the caption carry the takeaway.

What about decorative charts?

Truly decorative graphics get aria-hidden, but data charts are almost never decorative.

Do I still need a data table?

Yes, for anyone who needs exact values.

Permalink to "Related"

← Back to Accessible Names & Descriptions for Data Widgets