Making SVG Charts Accessible to Screen Readers
Making SVG charts accessible to screen readers requires a combination of semantic ARIA attributes, internal structural elements, and text descriptions. This guide outlines the essential markup needed to transform visual SVG data visualizations into accessible components, covering root element definitions, title and description associations, grouping semantics, and decorative element handling.
1. Configure the Root
<svg> Element
By default, screen readers may ignore SVG elements, treat them
inconsistently, or announce redundant structural paths. To ensure the
SVG is announced as a cohesive graphic, define the following attributes
on the <svg> root:
role="img": Informs assistive technologies to treat the entire SVG as a single image.aria-labelledby="title-id": Connects the SVG to its internal<title>element for a concise label.aria-describedby="desc-id": Connects the SVG to its internal<desc>element for a detailed explanation of the chart’s data.focusable="false": Prevents older versions of Internet Explorer and certain screen readers from placing an empty keyboard focus stop on the SVG wrapper.
<svg
role="img"
aria-labelledby="chart-title"
aria-describedby="chart-desc"
focusable="false"
viewBox="0 0 500 300">2. Include
<title> and <desc> Tags
Place <title> and <desc>
elements as the first direct children of the <svg>
element:
<title>: Acts as the accessible name of the chart (similar to thealttext on an<img>tag). Keep it brief, such as “Quarterly Revenue 2024”.<desc>: Acts as the accessible description. Provide a summary of the data trends, the highest/lowest data points, and the chart type.
<title id="chart-title">Monthly Active Users in 2024</title>
<desc id="chart-desc">A bar chart showing user growth from 10,000 in January to 45,000 in December, with the highest surge occurring in Q3.</desc>3. Hide Decorative Elements
Charts contain decorative lines, grid backgrounds, tick marks, and
axes that add visual context but create noise for screen readers. Hide
these elements using the aria-hidden="true" attribute on
individual elements or groups (<g>).
<g class="grid-lines" aria-hidden="true">
<line x1="0" y1="50" x2="500" y2="50" stroke="#e0e0e0" />
<line x1="0" y1="100" x2="500" y2="100" stroke="#e0e0e0" />
</g>4. Structure Individual Data Points (Optional)
If individual bars, points, or slices must be exposed to screen readers or focusable via keyboard:
- Apply
role="graphics-symbol"orrole="img"to each segment. - Provide an explicit
aria-labeldetailing the category and value. - Add
tabindex="0"if the user needs to focus on individual data points interactively.
<rect
x="20" y="50" width="30" height="150"
role="img"
aria-label="January: 10,000 users"
tabindex="0" />5. Provide an Accessible HTML Data Alternative
While proper SVG markup makes the graphic recognizable to screen
readers, complex data visualizations are best consumed in a structured
tabular format. Pair the SVG with a visually hidden HTML
<table> using CSS screen-reader-only utility
classes:
<div class="sr-only">
<table>
<caption>Monthly Active Users in 2024</caption>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Users</th>
</tr>
</thead>
<tbody>
<tr><td>January</td><td>10,000</td></tr>
<tr><td>December</td><td>45,000</td></tr>
</tbody>
</table>
</div>Complete Accessible SVG Example
<svg
role="img"
aria-labelledby="chart-title"
aria-describedby="chart-desc"
focusable="false"
viewBox="0 0 400 200"
xmlns="http://www.w3.org/2000/svg">
<title id="chart-title">Quarterly Sales Performance</title>
<desc id="chart-desc">Bar chart representing sales figures across four quarters, peaking in Q4 at $80,000.</desc>
<!-- Decorative Axis -->
<g class="axes" aria-hidden="true">
<line x1="40" y1="10" x2="40" y2="170" stroke="#333" />
<line x1="40" y1="170" x2="380" y2="170" stroke="#333" />
</g>
<!-- Data Bars -->
<g class="chart-data">
<rect x="60" y="90" width="40" height="80" fill="#007acc" role="img" aria-label="Q1: $40,000" />
<rect x="140" y="70" width="40" height="100" fill="#007acc" role="img" aria-label="Q2: $50,000" />
<rect x="220" y="50" width="40" height="120" fill="#007acc" role="img" aria-label="Q3: $60,000" />
<rect x="300" y="10" width="40" height="160" fill="#007acc" role="img" aria-label="Q4: $80,000" />
</g>
</svg>