What a screen reader gets

The table stays in the page. It is hidden from sight, but screen readers read it like any other table: the names of the rows and columns, and every number. The drawing is hidden from screen readers, with aria-hidden="true", so they do not read everything twice.

The button shows the table that a screen reader reads, under the chart.

Apples picked
thousands
Spring 58
Summer 72
Autumn 70
Winter 41
HTML
<figure id="a11y-table" data-chart="column" data-chart-table="print">
	<figcaption><b>Apples picked</b><br><span>thousands</span></figcaption>
	<table>
		<tbody>
			<tr><th>Spring</th><td>58</td></tr>
			<tr><th>Summer</th><td>72</td></tr>
			<tr><th>Autumn</th><td>70</td></tr>
			<tr><th>Winter</th><td>41</td></tr>
		</tbody>
	</table>
</figure>

Give the chart a title with a figcaption. Tablechart makes it the name of the figure and of the table, with aria-labelledby. So a screen reader that jumps to the table also reads the title and the unit. If the figure or the table already has a name, with aria-label, aria-labelledby or a caption, it keeps that name.

A screen reader does not read a line break. So Tablechart puts a full stop before each br in the title, hidden from sight, and a screen reader pauses between the title and the subtitle. If the line already ends with a full stop, a question mark, a colon or a comma, nothing is added.

If the chart has no figcaption, add aria-label to the figure, such as aria-label="Apples picked, in thousands".

Numbers that do not fit

Some charts do not show all their numbers: a stack with small parts, a narrow chart, or a line chart with lines close together. The numbers are still in the table, so screen readers read them. Pointing at a row, or tapping it, shows them in a tooltip.

To show the table under the chart as well, add data-chart-table="always" to the figure. This chart has three lines close together, so it leaves numbers out. The table under it has them all.

Apples per tree
Year North South East
2018 41 38 35
2019 45 44 42
2020 48 47 49
2021 52 50 51
2022 55 56 53
2023 58 57 59
2024 61 60 62
2025 64 66 63
HTML
<figure data-chart="line" data-chart-table="always">
	<figcaption><b>Apples per tree</b></figcaption>
	<table>
		<thead>
			<tr><th>Year</th><th>North</th><th>South</th><th>East</th></tr>
		</thead>
		<tbody>
			<tr><th>2018</th><td>41</td><td>38</td><td>35</td></tr>
			<tr><th>2019</th><td>45</td><td>44</td><td>42</td></tr>
			<tr><th>2020</th><td>48</td><td>47</td><td>49</td></tr>
			<tr><th>2021</th><td>52</td><td>50</td><td>51</td></tr>
			<tr><th>2022</th><td>55</td><td>56</td><td>53</td></tr>
			<tr><th>2023</th><td>58</td><td>57</td><td>59</td></tr>
			<tr><th>2024</th><td>61</td><td>60</td><td>62</td></tr>
			<tr><th>2025</th><td>64</td><td>66</td><td>63</td></tr>
		</tbody>
	</table>
</figure>

In print and PDF

On screen, the tooltip shows numbers that are left out. On paper there is no tooltip, so a chart that leaves numbers out also needs its table. data-chart-table, or the table option for all charts, says when the table is shown under the chart:

Value On screen In print and PDF
never Hidden Hidden. The default.
auto Hidden Shown, if the chart does not show all its numbers
print Hidden Always shown
always Shown Shown

If your pages become PDFs, use auto. Then a table only takes room on the page when the chart needs it.

JS
init({ table: "auto" });

Whether numbers are left out depends on the width of the chart. auto uses the width the chart has on the page.

Not only colour

Lines are told apart by their points as well: filled and open circles, squares and diamonds. A line can also be dashed or dotted. The button shows the chart without colour, as some people see it.

CSS
.a11y-colours {
	--tablechart-color-1: #c2410c;
	--tablechart-color-2: #15803d;
	--tablechart-color-3: #1d4ed8;
	--tablechart-color-4: #a21caf;
}
.is-grey .demo {
	filter: grayscale(1);
}
Year North South East West
2016 41 30 22 12
2019 58 39 35 20
2022 77 52 41 33
2025 105 61 70 45
HTML
<figure class="a11y-colours" data-chart="line" data-chart-legend>
	<table>
		<thead>
			<tr><th>Year</th><th>North</th><th data-line="dashed">South</th><th>East</th><th data-marker="diamond open">West</th></tr>
		</thead>
		<tbody>
			<tr><th>2016</th><td>41</td><td>30</td><td>22</td><td>12</td></tr>
			<tr><th>2019</th><td>58</td><td>39</td><td>35</td><td>20</td></tr>
			<tr><th>2022</th><td>77</td><td>52</td><td>41</td><td>33</td></tr>
			<tr><th>2025</th><td>105</td><td>61</td><td>70</td><td>45</td></tr>
		</tbody>
	</table>
</figure>
  • A number inside a bar is dark or light, whichever reads on the colour of the bar.
  • If you set your own colours, check that they contrast enough with the background: 3:1 for bars and lines, and 4.5:1 for a number inside a bar.

The total of a donut

If a donut has no total row, the number in the middle is the sum of the slices. Tablechart adds it to the table, in a hidden row at the bottom, so screen readers read it with a name: "Total, 74.5". The totallabel option sets the name.

Annotations

The text of an annotation, such as +24% on a bracket, stays in the page under the table, hidden from sight. Screen readers read it there. The badge in the drawing is hidden from them.

Without JavaScript

If JavaScript does not run, there is no chart. The table is then shown instead, with its title.

A chart with data-chart-src has no table until JavaScript has read the JSON file. If JavaScript does not run, or the file cannot be read, there is no table and no chart. Write the table in the HTML instead of as a JSON data source if you want to be sure that the data (as a table then) is always available.

Keyboard

The table is the way to the numbers for screen readers, and they move through it with their own keys. The tooltip only works with a pointer or a tap. If people who use a keyboard, without a screen reader, must be able to read every number, show the table with data-chart-table="always".

Zoom and text size

All text is HTML, sized in em. It follows the text size and the zoom of the browser, and stays sharp. Long names beside the bars of a bar chart wrap onto more lines.

Motion

If the visitor has asked for reduced motion in their system settings, charts are shown without animation.

Language

Set the lang attribute on the html element, such as lang="en". Screen readers use it to read the text in the right language, and Tablechart uses it to format the numbers. See Numbers.

Standards

Websites in the European Union must meet the European Accessibility Act, which refers to the standard EN 301 549, and through it to WCAG 2.1 at level AA. For a chart, the most important requirements are a text alternative (WCAG 1.1.1) and information that is available as structure (WCAG 1.3.1). A real data table meets both, and Tablechart keeps that table in the page.

Tablechart helps with these requirements, but whether a website meets them depends on the whole website. Test your own pages, for example with a screen reader.