Responsive tables
The introduction of smartphones increasingly led web designers to avoid traditional "bulky" HTML tables - because these would exceed the limited screen dimensions. Others tried to find ways to change the layout of tables so they would not need so much horizontal space anymore. Responsive tables were born. But to make them accessible, the use of some ARIA is essential.
Tables - a relic of days gone by?
Tables exist since the very early days of the internet. In and by themselves, their layout is meant to have a lot of horizontal space available.
Since portable devices like smartphones have become increasingly popular, screens have tended to become smaller and smaller. Alas, the use of traditional tables tends to be avoided by many modern websites (to prevent the need of horizontal scrolling).
On the other side, there have also been attempts to change the layout of traditional tables so they would fit these new requirements. Sadly, most of these attempts left accessibility behind. So we show you to change a table's visual appearance while keeping accessibility intact.
Saving space
Instead of transforming a traditional table's full layout into a responsive one (as will be explained below), it can be useful already to simply hide some of its elements on smaller screens.
Hiding negligible data
The following table about hobbies displays columns for a "Name", a "Description" and a link to "Additional resources".
As the description in fact simply is taken from the linked additional resources, we can easily hide it on narrow view to save horizontal space (if you haven't done this yet, go back and read Hiding elements from all devices). In the following example, please resize your browser to trigger narrow view.
Table with hidden column in narrow view
<table>
<caption>My Hobbies</caption>
<thead>
<tr>
<th>
Name
</th>
<th class="hidden-narrow">
Description
</th>
<th>
Additional Resources
</th>
</tr>
</thead>
<tbody>
<tr>
<th>
Playing Soccer
</th>
<td class="hidden-narrow">
Soccer is a team sport played between two teams of eleven players with a spherical ball.
</td>
<td>
<a href="https://en.wikipedia.org/wiki/Association_football">Wikipedia</a>
</td>
</tr>
<tr>
<th>
Dancing
</th>
<td class="hidden-narrow">
Dance is a performing art form consisting of purposefully selected sequences of human movement.
</td>
<td>
<a href="https://en.wikipedia.org/wiki/Dance">Wikipedia</a>
</td>
</tr>
<tr>
<th>
Gardening
</th>
<td class="hidden-narrow">
Gardening is the practice of growing and cultivating plants as part of horticulture.
</td>
<td>
<a href="https://en.wikipedia.org/wiki/Gardening">Wikipedia</a>
</td>
</tr>
</tbody>
</table>
table {
border-collapse: collapse;
}
thead th {
background-color: lightpink;
}
tbody th {
background-color: lightgreen;
}
th, td {
border: 1px solid;
}
@media only screen and (max-width: 600px) {
.hidden-narrow {
display: none;
}
}
Category |
Result |
Date |
Keyboard only |
✔ (pass) pass
|
- |
2018-4-17 |
NVDA 2018.1 + FF Quantum 59.0.2 |
✔ (pass) pass
|
- |
2018-4-17 |
JAWS 2018.3 + IE 11 |
✔ (pass) pass
|
- |
2018-4-23 |
JAWS 2018.3 + FF ESR 52.7.3 |
✔ (pass) pass
|
- |
2018-4-17 |
By the way, we added distinctive background colours so it will be easier for you to spot any differences.
Replacing bulky elements
In the following example, the bulky "Wikipedia" links are hidden, and only small icons are shown in narrow view.
Table with smaller elements in narrow view
<table>
<caption>My Hobbies</caption>
<thead>
<tr>
<th>
Name
</th>
<th>
Description
</th>
<th>
Additional Resources
</th>
</tr>
</thead>
<tbody>
<tr>
<th>
Playing Soccer
</th>
<td>
Soccer is a team sport played between two teams of eleven players with a spherical ball.
</td>
<td>
<a href="https://en.wikipedia.org/wiki/Association_football"><span class="hidden-narrow">Wikipedia</span><img alt="Wikipedia" class="hidden-wide" src="wiki.png" /></a>
</td>
</tr>
<tr>
<th>
Dancing
</th>
<td>
Dance is a performing art form consisting of purposefully selected sequences of human movement.
</td>
<td>
<a href="https://en.wikipedia.org/wiki/Dance"><span class="hidden-narrow">Wikipedia</span><img alt="Wikipedia" class="hidden-wide" src="wiki.png" /></a>
</td>
</tr>
<tr>
<th>
Gardening
</th>
<td>
Gardening is the practice of growing and cultivating plants as part of horticulture.
</td>
<td>
<a href="https://en.wikipedia.org/wiki/Gardening"><span class="hidden-narrow">Wikipedia</span><img alt="Wikipedia" class="hidden-wide" src="wiki.png" /></a>
</td>
</tr>
</tbody>
</table>
table {
border-collapse: collapse;
}
thead th {
background-color: lightpink;
}
tbody th {
background-color: lightgreen;
}
th, td {
border: 1px solid;
}
img {
width: 32px;
height: 32px;
}
@media only screen and (max-width: 600px) {
.hidden-narrow {
display: none;
}
}
@media only screen and (min-width: 601px) {
.hidden-wide {
display: none;
}
}
Category |
Result |
Date |
Keyboard only |
✔ (pass) pass
|
- |
2018-4-17 |
NVDA 2018.1 + FF Quantum 59.0.2 |
✔ (pass) pass
|
- |
2018-4-17 |
JAWS 2018.3 + IE 11 |
✔ (pass) pass
|
- |
2018-4-23 |
JAWS 2018.3 + FF ESR 52.7.3 |
✔ (pass) pass
|
- |
2018-4-17 |
Please do not forget to set a proper alternative text to those icons.
Changing the visual layout
Sometimes, the visual layout of a table needs to be changed completely to fit small screens.
As we already know: to alter a table's visual appearance, the display
property can be changed, and some ARIA needs to be added (if you haven't done this yet, go back and read Changing a table's visual layout). Take a look at the following example of a responsive table: when resizing the browser, you will see all elements stack on top of each other.
Table with block elements in narrow view
<table role="grid">
<caption>My Hobbies</caption>
<thead role="presentation">
<tr role="row">
<th role="columnheader">
Name
</th>
<th role="columnheader">
Description
</th>
<th role="columnheader">
Additional Resources
</th>
</tr>
</thead>
<tbody role="presentation">
<tr role="row">
<th role="rowheader">
Playing Soccer
</th>
<td role="gridcell">
Soccer is a team sport played between two teams of eleven players with a spherical ball.
</td>
<td role="gridcell">
<a href="https://en.wikipedia.org/wiki/Association_football">Wikipedia</a>
</td>
</tr>
<tr role="row">
<th role="rowheader">
Dancing
</th>
<td role="gridcell">
Dance is a performing art form consisting of purposefully selected sequences of human movement.
</td>
<td role="gridcell">
<a href="https://en.wikipedia.org/wiki/Dance">Wikipedia</a>
</td>
</tr>
<tr role="row">
<th role="rowheader">
Gardening
</th>
<td role="gridcell">
Gardening is the practice of growing and cultivating plants as part of horticulture.
</td>
<td role="gridcell">
<a href="https://en.wikipedia.org/wiki/Gardening">Wikipedia</a>
</td>
</tr>
</tbody>
</table>
table {
border-collapse: collapse;
}
thead th {
background-color: lightpink;
}
tbody th {
background-color: lightgreen;
}
th, td {
border: 1px solid;
}
@media only screen and (max-width: 600px) {
table {
display: block;
border-bottom: 1px solid;
}
caption, tr, tbody {
display: block;
}
td, th {
border-bottom: 0;
padding: 4px 8px;
display: block;
}
th {
text-align: left;
}
}
Category |
Result |
Date |
Keyboard only |
✔ (pass) pass
|
- |
2018-4-17 |
NVDA 2018.1 + FF Quantum 59.0.2 |
✔ (pass) pass
|
- |
2018-4-17 |
JAWS 2018.3 + IE 11 |
✔ (pass) pass
|
- |
2018-4-23 |
JAWS 2018.3 + FF ESR 52.7.3 |
✔ (pass) pass
|
- |
2018-4-17 |
As the table is enhanced using ARIA, screen reader users are very happy with this result.
Optimisation for visual users
Visually though, our table is not fully appealing yet, because in narrow view, the table headers' position on top of the table feels wrong.

Hiding table headers visually
In a first attempt, we can hide them visually in narrow view (if you haven't done this yet, go back and read Hiding elements visually by moving them off-screen). This way, they keep working for screen readers.
Table with visually hidden headers in narrow view
<table role="grid">
<caption>My Hobbies</caption>
<thead role="presentation">
<tr role="row">
<th role="columnheader">
Name
</th>
<th role="columnheader">
Description
</th>
<th role="columnheader">
Additional Resources
</th>
</tr>
</thead>
<tbody role="presentation">
<tr role="row">
<th role="rowheader">
Playing Soccer
</th>
<td role="gridcell">
Soccer is a team sport played between two teams of eleven players with a spherical ball.
</td>
<td role="gridcell">
<a href="https://en.wikipedia.org/wiki/Association_football">Wikipedia</a>
</td>
</tr>
<tr role="row">
<th role="rowheader">
Dancing
</th>
<td role="gridcell">
Dance is a performing art form consisting of purposefully selected sequences of human movement.
</td>
<td role="gridcell">
<a href="https://en.wikipedia.org/wiki/Dance">Wikipedia</a>
</td>
</tr>
<tr role="row">
<th role="rowheader">
Gardening
</th>
<td role="gridcell">
Gardening is the practice of growing and cultivating plants as part of horticulture.
</td>
<td role="gridcell">
<a href="https://en.wikipedia.org/wiki/Gardening">Wikipedia</a>
</td>
</tr>
</tbody>
</table>
table {
border-collapse: collapse;
}
thead th {
background-color: lightpink;
}
tbody th {
background-color: lightgreen;
}
th, td {
border: 1px solid;
}
@media only screen and (max-width: 600px) {
table {
display: block;
border-bottom: 1px solid;
}
caption, tr, tbody {
display: block;
}
thead {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
td, th {
border-bottom: 0;
padding: 4px 8px;
display: block;
}
th {
text-align: left;
}
}
Category |
Result |
Date |
Keyboard only |
✔ (pass) pass
|
- |
2018-4-17 |
NVDA 2018.1 + FF Quantum 59.0.2 |
✔ (pass) pass
|
- |
2018-4-17 |
JAWS 2018.3 + IE 11 |
✔ (pass) pass
|
- |
2018-4-23 |
JAWS 2018.3 + FF ESR 52.7.3 |
✔ (pass) pass
|
- |
2018-4-17 |
Adding visual table header per element
It would be even more beautiful if the table headers could be displayed visually next to each table cell. For this, we have to add them in each cell, but display them only in narrow view.
But this is redundant information for screen readers, so we use aria-hidden="true"
, trying to hide those additional table headers again. This works great with NVDA, while JAWS keeps announcing them (but we can live with that).
Table with added headers in narrow view
<table role="grid">
<caption>My Hobbies</caption>
<thead role="presentation">
<tr role="row">
<th role="columnheader">
Name
</th>
<th role="columnheader">
Description
</th>
<th role="columnheader">
Additional Resources
</th>
</tr>
</thead>
<tbody role="presentation">
<tr role="row">
<th role="rowheader">
<span aria-hidden="true" class="narrow-th">Name: </span>Playing Soccer
</th>
<td role="gridcell">
<span aria-hidden="true" class="narrow-th">Description: </span>Soccer is a team sport played between two teams of eleven players with a spherical ball.
</td>
<td role="gridcell">
<span aria-hidden="true" class="narrow-th">Additional Resources: </span><a href="https://en.wikipedia.org/wiki/Association_football">Wikipedia</a>
</td>
</tr>
<tr role="row">
<th role="rowheader">
<span aria-hidden="true" class="narrow-th">Name: </span>Dancing
</th>
<td role="gridcell">
<span aria-hidden="true" class="narrow-th">Description: </span>Dance is a performing art form consisting of purposefully selected sequences of human movement.
</td>
<td role="gridcell">
<span aria-hidden="true" class="narrow-th">Additional Resources: </span><a href="https://en.wikipedia.org/wiki/Dance">Wikipedia</a>
</td>
</tr>
<tr role="row">
<th role="rowheader">
<span aria-hidden="true" class="narrow-th">Name: </span>Gardening
</th>
<td role="gridcell">
<span aria-hidden="true" class="narrow-th">Description: </span>Gardening is the practice of growing and cultivating plants as part of horticulture.
</td>
<td role="gridcell">
<span aria-hidden="true" class="narrow-th">Additional Resources: </span><a href="https://en.wikipedia.org/wiki/Gardening">Wikipedia</a>
</td>
</tr>
</tbody>
</table>
table {
border-collapse: collapse;
}
thead th {
background-color: lightpink;
}
tbody th {
background-color: lightgreen;
}
th, td {
border: 1px solid;
}
.narrow-th {
font-weight: bold;
background-color: yellow;
}
@media only screen and (max-width: 600px) {
table {
display: block;
border-bottom: 1px solid;
}
caption, tr, tbody {
display: block;
}
thead {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
td, th {
border-bottom: 0;
padding: 4px 8px;
display: block;
}
th {
text-align: left;
}
}
@media only screen and (min-width: 601px) {
.narrow-th {
display: none;
}
}
Category |
Result |
Date |
Keyboard only |
✔ (pass) pass
|
- |
2018-4-17 |
NVDA 2018.1 + FF Quantum 59.0.2 |
✔ (pass) pass
|
- |
2018-4-17 |
JAWS 2018.3 + IE 11 |
✔ (pass) pass
|
- |
2018-4-23 |
JAWS 2018.3 + FF ESR 52.7.3 |
✔ (pass) pass
|
- |
2018-4-17 |
Final result
There we are: here you have the perfectly accessible responsive table.

Admittedly, this has become pretty complex now. But you can easily generate this automatically - even with some post-processing JavaScript.
This solution will deliver a very good experience to all kinds of users. So in our opinion, it is totally worth the effort.