Is there any way to accessibly hide a table caption without breaking how screen readers interpret the rest of the table? Hiding a <caption>
with typically recommended styles for hiding an element visually breaks the behavior of VoiceOver, causing it to skip the last row in the table when reading through linearly using the "next" keystroke. (It is possible to force VoiceOver into the last row by explicitly navigating down a column, but that requires the user to know to do this.)
I recognize this may be a bug in VoiceOver itself, but if there's a clean workaround, that would be ideal since WCAG requires accessibility with actually available assistive technology.
Here's a minimalist example to demonstrate:
Update: The style rules below are the standard rules used in the Magento framework to visually hide elements while leaving them accessible to screen readers. The key rule causing the VoiceOver behavior is the position: absolute
; however, if this is simply removed, the layout flow is impacted.
caption {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
<table>
<caption>Table of Fruits</caption>
<thead>
<tr>
<th>Fruit</th>
<th>Color</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>Red</td>
</tr>
<tr>
<td>Pear</td>
<td>Green</td>
</tr>
</tbody>
</table>
<p>Voiceover will jump straight from "Red" in prior table to this paragraph, skipping the last row.</p>
Use style. display="none" and style. display="block" .
The <caption> tag defines a table caption. The <caption> tag must be inserted immediately after the <table> tag. Tip: By default, a table caption will be center-aligned above a table. However, the CSS properties text-align and caption-side can be used to align and place the caption.
<caption>: The Table Caption element. The <caption> HTML element specifies the caption (or title) of a table.
Well... I see that you are using a caption
tag just for accessibility, which means that you don't want to show it visually; I suggest simply not using it and instead use aria-label in your table
tag, which will make it accessible for screen readers.
<table aria-label="Table of fruits"> ... </table>
Read the first paragraph of this page to get an idea about aria-label
usage.
<th>
Needs <tr>
as a Parent to be ValidThe OP (Original Post) code didn't have a <tr>
in the <thead>
which could be the reason why the last <tr>
is being skipped. Invalid HTML has a tendency to confuse applications such as VoiceOver.
Disclaimer: Not Tested - Caveat Emptor
The following demo has three <table>s
with identical HTML markup, CSS rules, and text content. Each <caption>
has a different .class
that employ a specific method of hiding content:
.clipped - Assuming that clipping content needs a length: clip: rect(0, 0, 0, 0);
looks dubious. Some other properties and values looked to be ad-hoc as well so try replacing caption {...}
rule set with:
.clipped { position: absolute !important; height: 1px; width: 1px; overflow: hidden; clip: rect(1px, 1px, 1px, 1px); }
.transparent - This is simply assigning a transparent color to text. Height is still there (which VoiceOver requires), but it can be adjusted if needed. opacity: 0
is also an option, but there are certain situations in which opacity: 0
is considered the same as visibility: hidden
(which VoiceOver ignores).
.transparent { color: rgba(0, 0, 0, 0); }
.collapsed - This collapses an element's content but retains its height so VoiceOver might recognize it.
.collapsed { visibility: collapse; }
table {
border: 1px solid #000;
table-layout: fixed;
border-collapse: collapse;
min-width: 200px;
}
th,
td {
width: 50%;
border: 1px solid #000;
}
.clipped {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
}
.transparent {
color: rgba(0, 0, 0, 0);
}
.collapsed {
visibility: collapse;
}
<table>
<caption class='clipped'>CAPTION</caption>
<thead><tr><th>TH</th><th>TH</th></tr></thead>
<tbody><tr><td>TD</td><td>TD</td></tr>
<tr><td>TD</td><td>TD</td></tr></tbody>
</table>
<table>
<caption class='transparent'>CAPTION</caption>
<thead><tr><th>TH</th><th>TH</th></tr></thead>
<tbody><tr><td>TD</td><td>TD</td></tr>
<tr><td>TD</td><td>TD</td></tr></tbody>
</table>
<table>
<caption class='collapsed'>CAPTION</caption>
<thead><tr><th>TH</th><th>TH</th></tr></thead>
<tbody><tr><td>TD</td><td>TD</td></tr>
<tr><td>TD</td><td>TD</td></tr></tbody>
</table>
<p>The <abbr title="Original Post"><b>OP</b></abbr> code didn't have a <code><tr></code> in the <code><thead></code> which could be the reason why the last <code><tr></code> is being skipped.</p>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With