Enable

Accessible Tables

When coding tabular data on a webpage, you should use the <table> tag. Some developers, surprisingly don't do this . Some also don't realize it's a bad idea to use flexbox to style tabular data. I think the aversion to using <table> markup comes from the bad old-school way developers, who couldn't use CSS back in the 90s, used to use table for layout (which you should never do now with a small exception for those who have to code HTML emails).

Many web developers who use <table> markup, however, don't know there are some additional code they need to make them accessible (even the CSS tricks so called "Complete" Guide to the Table Element doesn't really cover these items adequately, in my opinion):

How Screen Reader Users Navigate Tables

Screen-reader users should be able to navigate the table using their screen-reader's built in navigation:

A Simple Table

Go through the the walkthrough below to ensure you are adding all the markup needed.

Just a simple table. Walkthrough the HTML code below and make sure you are adding all the things that make tables accessible in your work.

Family Birthdays
Name
Age Birthday
Jackie 5 January 1
Beth 8 March 1
Birthday Delta 59 days.

Example code explanation

Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.

☜ Scroll to read full source ☞

                    
                

A Simple Table with the caption placed inside a figcaption tag

This is a great solution to make CSS styling easier for developers.

Note that the caption is on the bottom, instead of the top of the table.

Name Age Birthday
Jackie 5 April 5
Beth 8 January 14
Family Birthdays (Table Coded Using Figcaption)

Example code explanation

Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.

☜ Scroll to read full source ☞

                    
                

A Complex Table Made Using HTML5

If you already are using a component similar to this in existing work that is not accessible, go to the developer walkthrough of this section to see we made our implementation accessible.

Complex tables may have headings for column groups as well as individual columns. In these circumstances, use scope="colgroup" to them up. They should also use the headers attribute to ensure the relationships between table headers and table cells are correct.

Complex Table Example: Racing Times
Distances Females Males
Mary Betsy Joanne Matt Todd Jake
1 mile 8:32 7:43 9:51 7:55 7:01 7:51
5 km 28:04 26:47 38:15 27:27 24:21 24:31
10 km 1:01:16 55:38 1:56:01 57:04 50:35 50:45

Example code explanation

Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.

☜ Scroll to read full source ☞

                    
                

A Simple Table Made Using Aria Roles

This should only be done as a last result in existing code if a developer thought it was a good idea to code tabular data with a bunch of <div> tags and it would be too hard to recode.

This is relatively new to ARIA and may not be implemented by all assistive technologies. It should only be used when there is existing code that is not marked up as an HTML table, but looks and semantically contains tabular data.

Note: The structure your markup should be structured similar to the HTML structure used in the code walkthrough below, but if not, don't fret. If your existing markup has extra tags that are between what should be direct ancestors, you can tell the screen reader to pretend they are not there by marking them up as role="presentation" For example, here is how we would deal with an extra div descendant between a row and a list of cells:

☜ Scroll to read full source ☞

                    
                
Family Birthdays (coded using ARIA)
Name Age Birthday
Jackie 5 April 5
Beth 8 January 14

Example code explanation

Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.

☜ Scroll to read full source ☞

                    
                

A Complex Table Made Using Aria Roles

This should only be done as a last result in existing code if a developer thought it was a good idea to code tabular data with a bunch of <div> tags and it would be too hard to recode.

It takes real talent to code tables this way: It's wrong and it takes a lot of time. You really should reconsider recoding your tables with <table> tags instead. Your colleagues will thank you, I will thank you, and you know that you did a good deed.

To be honest, I felt really dirty coding this example. I hope you realize I took one for the team here. Please take my sacrifice seriously. Don't do this unless you are really in a bind.

Comparison Criteria ACME Widgets Our Competitor's Widgets
ACME Widgets compared to the competition
Power Usage (in kilowatt hours) 5 kWh 20 kWh
Costs for fuel per hour
$20
(Note: this is an estimate given current market value)
$100
Total Savings in one day $45600

Example code explanation

Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.

☜ Scroll to read full source ☞

                    
                

Sticky Table Header

This is a great way to style a table when there is a lot of data inside of it.

When you have a lot of data you need to present to the user, you may want to ensure that when sighted users scrolls down the page, the table's header is always visible. This is so they can always remember the association with the table data and what it respresents.

Another way of preserving this visual connection to the table headings and the table data is by using pagination tables. While they are effective, they are more complex and require JavaScript, while the "sticky table header" has quite a few advantages:

  1. It is CSS only.
  2. It is easily searchable within the browser ... no extra coding required!
  3. The UI is easy to understand and really straightforward.
  4. If there are links inside the table, and you are concerned about the amount of tabstops there are inside the table for keyboard users, you could use skip links around the table so they can skip this table entirely.

If you are not worried about large hits to a backend database for generating the data or a ridiculously huge HTTP payload, I would suggest considering the use of a table with a fixed table header. It has a way less complicated UI, and if marked up correctly, is totally accessible via screen readers and keyboard.

(Note: Data from this table was taken from World Population Review).

Sticky Header Example: GDP of the World Nations
Sighted users can use the arrow keys to scroll through the table.
Rank Name GDP (IMF '19) GDP (UN '16) GDP Per Capita Population
1 United States 22.20 trillion 18.62 trillion $66,678 332,915,073
2 China 15.47 trillion 11.22 trillion $10,710 1,444,216,107
3 Japan 5.50 trillion 4.94 trillion $43,597 126,050,804
4 Germany 4.16 trillion 3.48 trillion $49,548 83,900,473
5 India 3.26 trillion 2.26 trillion $2,338 1,393,409,038
6 United Kingdom 2.93 trillion 2.65 trillion $42,915 68,207,116
7 France 2.88 trillion 2.47 trillion $43,959 65,426,179
8 Italy 2.09 trillion 1.86 trillion $34,629 60,367,477
9 Brazil 2.06 trillion 1.80 trillion $9,638 213,993,437
10 Canada 1.83 trillion 1.53 trillion $48,137 38,067,903
11 South Korea 1.74 trillion 1.41 trillion $34,000 51,305,186
12 Russia 1.67 trillion 1.25 trillion $11,428 145,912,025
13 Spain 1.50 trillion 1.24 trillion $32,026 46,745,216
14 Australia 1.48 trillion 1.30 trillion $57,447 25,788,215
15 Mexico 1.30 trillion 1.08 trillion $9,963 130,262,216
16 Indonesia 1.21 trillion 932.26 billion $4,374 276,361,783
17 Netherlands 954.93 billion 777.23 billion $55,606 17,173,099
18 Turkey 809.55 billion 863.71 billion $9,519 85,042,738
19 Saudi Arabia 790.06 billion 639.62 billion $22,356 35,340,683
20 Switzerland 740.70 billion 668.85 billion $84,987 8,715,494
21 Poland 643.27 billion 471.40 billion $17,019 37,797,005
22 Taiwan 633.70 billion $26,564 23,855,010
23 Sweden 576.72 billion 514.48 billion $56,763 10,160,169
24 Belgium 553.78 billion 467.96 billion $47,607 11,632,326
25 Thailand 547.43 billion 407.03 billion $7,826 69,950,850
26 Argentina 515.35 billion 545.87 billion $11,300 45,605,826
27 Nigeria 496.12 billion 404.65 billion $2,347 211,400,708
28 Iran 495.69 billion 425.40 billion $5,830 85,028,759
29 Austria 481.68 billion 390.80 billion $53,265 9,043,070
30 United Arab Emirates 449.13 billion 348.74 billion $44,953 9,991,089
31 Norway 438.62 billion 371.07 billion $80,251 5,465,630
32 Ireland 405.19 billion 304.82 billion $81,315 4,982,907
33 Israel 403.96 billion 317.75 billion $45,958 8,789,774
34 Hong Kong 402.03 billion 320.91 billion $53,230 7,552,810
35 Malaysia 401.99 billion 296.53 billion $12,265 32,776,194
36 Singapore 391.88 billion 296.95 billion $66,457 5,896,686
37 Philippines 389.05 billion 304.91 billion $3,503 111,046,913
38 South Africa 386.73 billion 295.44 billion $6,441 60,041,994
39 Denmark 364.55 billion 306.90 billion $62,709 5,813,298
40 Colombia 352.81 billion 282.46 billion $6,882 51,265,844
41 Bangladesh 343.28 billion 220.84 billion $2,064 166,303,498
42 Egypt 331.36 billion 270.14 billion $3,178 104,258,327
43 Chile 313.56 billion 247.05 billion $16,321 19,212,361
44 Finland 289.24 billion 238.50 billion $52,131 5,548,360
45 Vietnam 282.37 billion 205.28 billion $2,876 98,168,833
46 Romania 263.13 billion 186.69 billion $13,757 19,127,774
47 Czech Republic 259.74 billion 195.31 billion $24,219 10,724,555
48 Portugal 249.91 billion 204.84 billion $24,578 10,167,925
49 Iraq 246.93 billion 160.02 billion $5,997 41,179,350
50 Peru 244.16 billion 192.21 billion $7,319 33,359,418
51 Greece 230.50 billion 192.69 billion $22,226 10,370,744
52 New Zealand 224.94 billion 187.52 billion $46,278 4,860,643
53 Qatar 204.01 billion 152.45 billion $69,615 2,930,528
54 Algeria 193.06 billion 159.05 billion $4,327 44,616,624
55 Hungary 177.73 billion 125.82 billion $18,448 9,634,164
56 Kazakhstan 177.32 billion 135.01 billion $9,335 18,994,962
57 Ukraine 147.17 billion 93.27 billion $3,386 43,466,819
58 Kuwait 143.00 billion 110.35 billion $33,036 4,328,550
59 Morocco 129.06 billion 103.61 billion $3,456 37,344,795
60 Slovakia 117.40 billion 89.77 billion $21,499 5,460,721
61 Kenya 109.12 billion 70.53 billion $1,984 54,985,698
62 Ecuador 107.73 billion 98.01 billion $6,022 17,888,475
63 Puerto Rico 104.12 billion 105.03 billion $36,813 2,828,255
64 Ethiopia 99.37 billion 70.31 billion $843 117,876,227
65 Angola 96.43 billion 106.92 billion $2,842 33,933,610
66 Dominican Republic 90.46 billion 71.58 billion $8,258 10,953,703
67 Sri Lanka 89.94 billion 81.32 billion $4,184 21,497,310
68 Guatemala 87.63 billion 68.76 billion $4,802 18,249,860
69 Oman 84.16 billion 63.17 billion $16,112 5,223,375
70 Panama 75.49 billion 55.19 billion $17,230 4,381,579
71 Luxembourg 73.69 billion 58.63 billion $116,086 634,814
72 Ghana 72.26 billion 42.79 billion $2,277 31,732,129
73 Bulgaria 71.75 billion 53.24 billion $10,403 6,896,663
74 Myanmar 71.40 billion 65.70 billion $1,303 54,806,012
75 Venezuela 70.11 billion 291.38 billion $2,442 28,704,954
76 Tanzania 64.89 billion $1,055 61,498,437
77 Croatia 64.59 billion 51.23 billion $15,824 4,081,651
78 Belarus 63.66 billion 47.41 billion $6,742 9,442,862
79 Costa Rica 63.46 billion 57.44 billion $12,349 5,139,052
80 Uruguay 63.42 billion 52.42 billion $18,197 3,485,151
81 Macau 62.16 billion 45.31 billion $94,409 658,394
82 Lebanon 60.62 billion 50.46 billion $8,955 6,769,146
83 Slovenia 58.21 billion 44.71 billion $28,004 2,078,724
84 Lithuania 57.60 billion 42.77 billion $21,414 2,689,862
85 Turkmenistan 57.06 billion 36.18 billion $9,327 6,117,924
86 Serbia 56.89 billion 38.30 billion $6,540 8,697,550
87 Uzbekistan 55.48 billion 67.78 billion $1,635 33,935,763
88 Dr Congo 52.48 billion 40.34 billion $568 92,377,993
89 Libya 50.42 billion 42.96 billion $7,246 6,958,532
90 Ivory Coast 49.88 billion 36.77 billion $1,844 27,053,629
91 Azerbaijan 47.43 billion 37.85 billion $4,639 10,223,342
92 Bolivia 47.05 billion 33.81 billion $3,976 11,832,940
93 Jordan 46.45 billion 38.65 billion $4,523 10,269,021
94 Paraguay 45.38 billion 27.17 billion $6,285 7,219,638
95 Cameroon 42.05 billion 32.22 billion $1,544 27,224,265
96 Bahrain 40.71 billion 32.18 billion $23,284 1,748,296
97 Latvia 38.10 billion 27.57 billion $20,409 1,866,942
98 Tunisia 35.15 billion 41.70 billion $2,945 11,935,766
99 Uganda 33.62 billion 25.31 billion $713 47,123,531
100 Estonia 33.23 billion 23.34 billion $25,080 1,325,185
101 Nepal 33.03 billion 20.91 billion $1,113 29,674,920
102 Yemen 31.39 billion 25.37 billion $1,029 30,490,640
103 Cambodia 29.31 billion 20.02 billion $1,730 16,946,438
104 El Salvador 28.20 billion 26.80 billion $4,326 6,518,499
105 Senegal 28.06 billion 14.60 billion $1,632 17,196,301
106 Iceland 26.82 billion 20.27 billion $78,115 343,353
107 Cyprus 26.35 billion 20.05 billion $21,675 1,215,584
108 Zimbabwe 25.81 billion 16.12 billion $1,710 15,092,171
109 Honduras 25.56 billion 21.52 billion $2,540 10,062,991
110 Zambia 25.27 billion 21.06 billion $1,336 18,920,651
111 Trinidad And Tobago 23.23 billion 24.09 billion $16,557 1,403,375
112 Papua New Guinea 22.11 billion 19.69 billion $2,425 9,119,010
113 Laos 22.01 billion 15.81 billion $2,983 7,379,358
114 Bosnia And Herzegovina 21.34 billion 16.91 billion $6,540 3,263,466
115 Botswana 20.87 billion 15.57 billion $8,707 2,397,241
116 Afghanistan 20.68 billion 20.24 billion $519 39,835,428
117 Mali 19.33 billion 14.00 billion $927 20,855,735
118 Georgia 18.89 billion 14.33 billion $4,746 3,979,765
119 Gabon 17.89 billion 13.86 billion $7,852 2,278,825
120 Albania 17.21 billion 11.86 billion $5,990 2,872,933
121 Jamaica 16.72 billion 14.06 billion $5,622 2,973,463
122 Malta 16.34 billion 11.00 billion $36,898 442,784
123 Mozambique 16.29 billion 10.93 billion $507 32,163,047
124 Burkina Faso 16.27 billion 11.70 billion $757 21,497,096
125 Mauritius 15.76 billion 12.22 billion $12,374 1,273,433
126 Mongolia 14.96 billion 11.16 billion $4,493 3,329,289
127 Namibia 14.63 billion 10.95 billion $5,653 2,587,344
128 Brunei 14.28 billion 11.40 billion $32,344 441,532
129 Armenia 13.87 billion 10.57 billion $4,672 2,968,127
130 Bahamas 13.71 billion 11.26 billion $34,542 396,913
131 North Macedonia 13.70 billion 10.75 billion $6,578 2,082,658
132 Guinea 13.60 billion 8.48 billion $1,008 13,497,244
133 Madagascar 13.54 billion 11.22 billion $476 28,427,328
134 Moldova 12.79 billion 6.77 billion $3,179 4,024,019
135 Chad 12.55 billion 11.27 billion $742 16,914,985
136 Nicaragua 12.46 billion 13.23 billion $1,859 6,702,385
137 Equatorial Guinea 12.26 billion 10.68 billion $8,458 1,449,896
138 Benin 12.13 billion 8.89 billion $974 12,451,040
139 Republic Of The Congo 11.37 billion 7.78 billion $2,009 5,657,013
140 Rwanda 11.06 billion 8.47 billion $833 13,276,513
141 Niger 10.63 billion 7.53 billion $423 25,130,817
142 Haiti 9.65 billion 7.65 billion $836 11,541,685
143 Kyrgyzstan 8.78 billion 6.55 billion $1,325 6,628,356
144 Somalia 8.34 billion 1.32 billion $510 16,359,504
145 Eritrea 8.12 billion 5.41 billion $2,254 3,601,467
146 Malawi 7.86 billion 5.32 billion $400 19,647,684
147 Tajikistan 7.84 billion 6.95 billion $804 9,749,627
148 Maldives 6.21 billion 4.22 billion $11,429 543,617
149 Togo 6.13 billion 4.45 billion $723 8,478,250
150 Montenegro 5.74 billion 4.37 billion $9,139 628,053
151 Mauritania 5.70 billion 4.67 billion $1,193 4,775,119
152 Fiji 5.67 billion 4.67 billion $6,281 902,906
153 Barbados 5.34 billion 4.55 billion $18,557 287,711
154 Eswatini 4.81 billion 4.01 billion $4,105 1,172,362
155 Guyana 4.61 billion 3.44 billion $5,832 790,326
156 Sierra Leone 4.22 billion 3.67 billion $518 8,141,343
157 Suriname 3.92 billion 3.28 billion $6,622 591,800
158 Burundi 3.71 billion 2.87 billion $303 12,255,433
159 Timor Leste 3.41 billion 2.70 billion $2,540 1,343,873
160 Liberia 3.22 billion 2.76 billion $621 5,180,203
161 Aruba 2.95 billion 2.67 billion $27,536 107,204
162 Bhutan 2.94 billion 2.21 billion $3,768 779,898
163 Lesotho 2.89 billion 2.24 billion $1,339 2,159,079
164 South Sudan 2.80 billion 6.53 billion $246 11,381,378
165 Djibouti 2.60 billion 1.89 billion $2,593 1,002,187
166 Central African Republic 2.48 billion 1.81 billion $505 4,919,981
167 Cape Verde 2.21 billion 1.64 billion $3,930 561,898
168 Belize 2.07 billion 1.74 billion $5,115 404,914
169 Saint Lucia 2.07 billion 1.40 billion $11,220 184,400
170 Gambia 1.87 billion 985.83 Mn $752 2,486,945
171 Antigua And Barbuda 1.81 billion 1.46 billion $18,323 98,731
172 Seychelles 1.74 billion 1.43 billion $17,582 98,908
173 San Marino 1.67 billion 1.59 billion $49,152 34,017
174 Guinea Bissau 1.67 billion 1.12 billion $828 2,015,494
175 Solomon Islands 1.61 billion 1.13 billion $2,283 703,996
176 Grenada 1.33 billion 1.02 billion $11,768 113,021
177 Saint Kitts And Nevis 1.12 billion 909.85 Mn $20,880 53,544
178 Vanuatu 994.00 Mn 837.52 Mn $3,161 314,464
179 Samoa 960.00 Mn 822.23 Mn $4,796 200,149
180 Saint Vincent And The Grenadines 903.00 Mn 765.32 Mn $8,116 111,263
181 Comoros 773.00 Mn 1.15 billion $870 888,451
182 Dominica 590.00 Mn 581.48 Mn $8,175 72,167
183 Sao Tome And Principe 527.00 Mn 342.78 Mn $2,359 223,368
184 Tonga 512.00 Mn 401.46 Mn $4,796 106,760
185 Micronesia 389.00 Mn 329.90 Mn $3,346 116,254
186 Palau 324.00 Mn 310.25 Mn $17,833 18,169
187 Marshall Islands 228.00 Mn 183.00 Mn $3,825 59,610
188 Kiribati 196.00 Mn 173.66 Mn $1,615 121,392
189 Nauru 117.00 Mn 103.47 Mn $10,758 10,876
190 Tuvalu 53.00 Mn 36.70 Mn $4,442 11,931
191 Andorra 2.86 billion $36,952 77,355
192 Bermuda 6.13 billion $98,685 62,090
193 British Virgin Islands 971.24 Mn $31,927 30,421
194 Cayman Islands 3.84 billion $57,808 66,497
195 Cook Islands 290.19 Mn $16,521 17,565
196 Cuba 89.69 billion $7,925 11,317,505
197 French Polynesia 5.42 billion $19,176 282,530
198 Palestine 13.40 billion $2,565 5,222,748
199 Greenland 2.28 billion $40,138 56,877
200 North Korea 16.79 billion $649 25,887,041
201 Liechtenstein 6.19 billion $161,926 38,250
202 Monaco 6.47 billion $163,701 39,511
203 Montserrat 62.05 Mn $12,468 4,977
204 Curacao 3.12 billion $18,941 164,798
205 Sint Maarten 1.07 billion $24,695 43,412
206 New Caledonia 9.45 billion $32,773 288,218
207 Pakistan 282.51 billion $1,254 225,199,937
208 Anguilla 337.52 Mn $22,327 15,117
209 Sudan 82.89 billion $1,846 44,909,353
210 Syria 22.16 billion $1,213 18,275,702
211 Turks And Caicos Islands 917.55 Mn $23,388 39,231

Example code explanation

Below is the HTML of the above example. Use the dropdown to highlight each of the individual steps that makes the example accessible.

☜ Scroll to read full source ☞