Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to accessibly hide table caption element?

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>
like image 729
Scott Buchanan Avatar asked Feb 26 '19 00:02

Scott Buchanan


People also ask

How do you hide table contents in HTML?

Use style. display="none" and style. display="block" .

How do you display the caption of the table at the bottom?

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.

Is caption in the table element?

<caption>: The Table Caption element. The <caption> HTML element specifies the caption (or title) of a table.


2 Answers

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.

like image 105
Mario Medrano Medrano Avatar answered Oct 30 '22 12:10

Mario Medrano Medrano


A Few Discrepancies

<th> Needs <tr> as a Parent to be Valid

The 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.


Three Methods

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:

  1. .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);
    }  
    
  2. .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);
    }  
    
  3. .collapsed - This collapses an element's content but retains its height so VoiceOver might recognize it.

    .collapsed {
      visibility: collapse;
    }
    

Demo

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>&lt;tr&gt;</code> in the <code>&lt;thead&gt;</code> which could be the reason why the last <code>&lt;tr&gt;</code> is being skipped.</p>
like image 34
zer00ne Avatar answered Oct 30 '22 12:10

zer00ne