Accessible SVG tables

SVG has no native semantics for representing structures like tables, but ARIA1.1 introduces a number of roles that can be used to polyfill the necessary semantic information.

If you’re using HTML, use the relevant HTML elements to create tables. The table, thead, tfooter, tbody, th, and td elements are purpose built to do the job. Don’t make things harder for yourself by reinventing the wheel.

That said, if you’re working with SVG (which doesn’t have elements for representing tables), then polyfilling the missing semantics with ARIA makes the SVG content more accessible for screen reader users.

Basic SVG table

Let’s take a simple SVG table as a working example:

>ExpensesSalesExpensesNetQ1$ 223$ 195$ 28Q2$ 183$ 70$ 113Q3$ 277$ 88$ 189Q4$ 402$ 133$ 269

Basic SVG table code

The SVG code looks like this:

<svg width="100%" height="100%" viewBox="0 0 370 160">>
<title>Expenses</title>

<g id='rowGroup' transform='translate(0, 0)'>
<rect x='25' y='40' width='310' height='20' fill='gainsboro'/>
<rect x='25' y='76' width='310' height='20' fill='gainsboro'/>

<text x='30' y='30' font-size='18px' font-weight='bold' fill='crimson' text-anchor='middle' role="row">
<tspan  x='100'>Sales</tspan>
<tspan   x='200'>Expenses</tspan>
<tspan  x='300'>Net</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan  x='30' dy='1.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q1</tspan>
<tspan  x='100'>$ 223</tspan>
<tspan  x='200'>$ 195</tspan>
<tspan  x='300'>$ 28</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan  x='30' dy='2.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q2</tspan>
<tspan  x='100'>$ 183</tspan>
<tspan  x='200'>$ 70</tspan>
<tspan  x='300'>$ 113</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan  x='30' dy='3.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q3</tspan>
<tspan  x='100'>$ 277</tspan>
<tspan  x='200'>$ 88</tspan>
<tspan  x='300'>$ 189</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan id="q4"  x='30' dy='4.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q4</tspan>
<tspan  x='100'>$ 402</tspan>
<tspan  x='200'>$ 133</tspan>
<tspan  x='300'>$ 269</tspan>
</text>
</g>
</svg>

Missing semantics

It looks like a table, but the samantic information exposed by SVG in the accessibility tree is not that of a table. According to the SVG Accessibility API Mappings (AAM), the exposed roles are:

  • graphics-document for the svg element;
  • graphics-symbol for the rect element;
  • group for the g element;
  • group or text (depending on the accessibility API) for the text element.

Note: the graphics-document and graphics-symbol roles are documented in the ARIA Graphics module, and the Graphics AAM.

There is an added complication: although these roles are supported by browsers and accessibility APIs, they are not well supported by screen readers. The group role is recognised by screen readers but is not communicated to users in this context, and neither the graphics-document or graphics-symbol roles is recognised at all. The text content is available to screen readers though.

Adding semantics

So in the absence of useful semantic information, we can use these ARIA roles as an accessibility polyfill:

Basic SVG table + ARIA

This SVG table looks the same, but thanks to the ARIA it can be navigated by screen reader users in the same way as an HTML table.

>ExpensesSalesExpensesNetQ1$ 223$ 195$ 28Q2$ 183$ 70$ 113Q3$ 277$ 88$ 189Q4$ 402$ 133$ 269

Basic SVG table + ARIA code

The updated code looks like this:

<svg width="100%" height="100%" viewBox="0 0 370 160">
<title>Expenses</title>

<g id='rowGroup' transform='translate(0, 0)' role="table">
<rect x='25' y='40' width='310' height='20' fill='gainsboro'/>
<rect x='25' y='76' width='310' height='20' fill='gainsboro'/>

<text x='30' y='30' font-size='18px' font-weight='bold' fill='crimson' text-anchor='middle' role="row">
<tspan role="columnheader" x='100'>Sales</tspan>
<tspan  role="columnheader" x='200'>Expenses</tspan>
<tspan role="columnheader" x='300'>Net</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan role="rowheader" x='30' dy='1.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q1</tspan>
<tspan role="cell" x='100'>$ 223</tspan>
<tspan role="cell" x='200'>$ 195</tspan>
<tspan role="cell" x='300'>$ 28</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan role="rowheader" x='30' dy='2.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q2</tspan>
<tspan role="cell" x='100'>$ 183</tspan>
<tspan role="cell" x='200'>$ 70</tspan>
<tspan role="cell" x='300'>$ 113</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan role="rowheader" x='30' dy='3.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q3</tspan>
<tspan role="cell" x='100'>$ 277</tspan>
<tspan role="cell" x='200'>$ 88</tspan>
<tspan role="cell" x='300'>$ 189</tspan>
</text>

<text x='30' y='30' font-size='18px' text-anchor='middle' role="row">
<tspan id="q4" role="rowheader" x='30' dy='4.5em' font-weight='bold' fill='crimson' text-anchor='start'>Q4</tspan>
<tspan role="cell" x='100'>$ 402</tspan>
<tspan role="cell" x='200'>$ 133</tspan>
<tspan role="cell" x='300'>$ 269</tspan>
</text>
</g>
</svg>

This has the advantage of being supported on multiple platforms, in multiple browsers, and with multiple screen readers. The ARIA tables demo includes information about browser and screen reader support for Windows, MacOS, iOS, and Android.

4 comments on “Accessible SVG tables”

Skip to Post a comment
  1. Comment by Kaz Tsuchiya (@caztcha)

    Hi, I am a web usability & accessibility professional in Japan, and I’m subscibing your blog feed. Thank you for your informative blog post every time!

    As for this post, I could understand how to make SVG table accessible (or semantic), but I just wondered when we should adopt SVG table instead of usual HTML “table” element. Could you give me an advise in which case should we use the SVG table? Or are there any merits to use the SVG table (than the HTML “table” markup) from the accessibility point of view?

    Thank you. 🙂

    1. Comment by Léonie Watson

      @Kaz Thanks.

      I wouldn’t recommend using SVG for tables by choice, but we’re not limited to building interfaces in HTML on the web.

      This is also the technique to use to make SVG data visualisations like bar charts, line graphs, and scatter plots more accessible to screen readers. I’m working on a follow-up post that explains how to do this.

      1. Comment by Kaz Tsuchiya (@caztcha)

        Thank you Léonie , I see your point! Looking forward to your follow-up posts. 🙂

  2. Comment by Martin

    Nice post, this was quite new for me. And could be a nice way to do a “responsive table” with some limitation though.

Comment on this post

Will not be published
Optional