Skip to content
easeweb
Search topics

Comparison tables with ticks and crosses that read as blank

A pricing table shows each plan's features as tick and cross icons hidden with aria-hidden, so a cell that says yes reads the same as an empty one.

WCAG 2.2
SC 1.1.1A
Required by
Section 508 · EN 301 549 (EU)
Broken <svg aria-hidden="true">
The accessibility problem illustrated: No vision:Does this plan have it?
01

The problem

Screen reader users can't tell which plans include a feature, because a cell with a tick reads the same as a cell with a cross or with nothing

02

Try it

Press Tab to move through the cells, and compare what you see with what is read

  • Broken 1: each Tab stands in for a screen reader moving to the next cell. A tick and a cross both have nothing to read.

  • Broken 2: the crosses are gone and those cells are empty. A tick and an empty cell have nothing to read, the same as each other.

  • Apply a fix. Go along the Single sign-on row. The one called Named ticks only leaves cells with nothing to read.

Broken Can you fix this?

FeatureStarterTeamBusiness
Unlimited projects
Shared folders
Single sign-on

Screen reader says:

(Tab to a cell)

A recreated demo. The broken version is intentionally inaccessible.

03

The fix

Put a word in every cell, including the ones with no tick

Before

Ticks and crosses hidden by the icon library

<table class="plans">  <thead>    <tr>      <th scope="col">Feature</th>      <th scope="col">Starter</th>      <th scope="col">Team</th>      <th scope="col">Business</th>    </tr>  </thead>  <tbody>    <tr>      <th scope="row">Shared folders</th>      <td>        <svg class="no" aria-hidden="true" viewBox="0 0 24 24">…</svg>      </td>      <td>        <svg class="yes" aria-hidden="true" viewBox="0 0 24 24">…</svg>      </td>      <td>        <svg class="yes" aria-hidden="true" viewBox="0 0 24 24">…</svg>      </td>    </tr>    …  </tbody></table>
What is wrong2 points

The headers here are right: each cell has its plan and its feature. What each cell says is where it fails.

  • The tick is hidden from assistive technology, and the cell has no other content, so "included" is lost.
  • The cross is hidden too, so "not included" is lost as well, and the two cells read the same.
After

Hidden words in each cell

<table class="plans">  <thead>    <tr>      <th scope="col">Feature</th>      <th scope="col">Starter</th>      <th scope="col">Team</th>      <th scope="col">Business</th>    </tr>  </thead>  <tbody>    <tr>      <th scope="row">Shared folders</th>      <td>        <svg class="no" aria-hidden="true" viewBox="0 0 24 24">…</svg>        <span class="visually-hidden">Not included</span>      </td>      <td>        <svg class="yes" aria-hidden="true" viewBox="0 0 24 24">…</svg>        <span class="visually-hidden">Included</span>      </td>      <td>        <svg class="yes" aria-hidden="true" viewBox="0 0 24 24">…</svg>        <span class="visually-hidden">Included</span>      </td>    </tr>    …  </tbody></table>
How it is fixed3 steps
  1. Leave the icon hidden, as the library renders it. It no longer has to speak.
  2. Add a clipped span to each cell with the value in words, "Included" or "Not included". The cell now has that as its text, in a screen reader's table reading and in a browser's translation of the page.
  3. In a table with empty cells, put "Not included" in the empty cell the same way. It stays empty on screen, and it now says no.

This fixes both Befores and passes 1.1.1. The table looks exactly as it did. On screen the value is still only a mark, or a blank, so anyone who doesn't read a tick as yes still has to guess.

Why this fix: Use native HTML first

Easily confused
04

Design ideas

A comparison table can stay light and still say yes and no

Six ways to draw which plan has which feature. Four say it in words a screen reader can read, whatever the look, and two leave it to the eye.

In the design file

  • Write the words for every kind of cell in the design file, such as Included and Not included, even where only a mark is drawn.
  • Give every cell that means no something to read, not an empty box.
  • Write the contrast beside each mark that carries the value, at least 3:1, and beside each word, at least 4.5:1.
  • Draw the table at phone width too, and show where the words go when the columns narrow.

Passes

  • FeatureStarterTeamBusiness
    Single sign-onNot includedNot includedIncluded
    Words in soft pills Included in a soft green pill, at 7.74:1, and Not included as plain grey text, at 7.56:1 on white. The table still scans by colour, and the words say it for anyone who can’t see the colour or the mark. It takes more width than a mark, so keep the labels short.
  • FeatureStarterTeamBusiness
    Members550Unlimited
    Single sign-onNot includedNot includedIncluded
    The value itself in each cell 5, 50 and Unlimited say more than three ticks would, and they are already text, so nothing needs naming. Use it where a feature has a limit, and write Not included in full rather than leaving a gap.
  • FeatureStarterTeamBusiness
    Single sign-on Not included Not included Included
    A filled badge against an outlined dash Keeps the light look of marks: a tick in a filled green disc, white on #1e7b34 at 5.33:1, against a dash in a thin outline. The two differ in shape and weight as well as colour, and each cell also holds words for a screen reader that the design doesn’t show.
  • Team

    Included

    • Shared folders

    Not included

    • Single sign-on
    Two lists under each plan No table: under each plan, the features sit under an Included heading and a Not included heading, so the words are said once and every line needs no mark. It suits a phone, and comparing plans side by side gets harder.

Fails

  • FeatureStarterTeamBusiness
    Single sign-on
    Green and red dotsWCAG 1.1.1 Tidy, and quick to scan for anyone who can see them. But a dot has no words, so the cell has nothing to read, and the two colours are only 1.24:1 against each other, so colour alone keeps them apart.
  • Team

    • Shared folders
    • Single sign-on
    Features that aren’t included, faded outWCAG 1.4.3 A common pricing card: what the plan lacks fades to pale grey, at 1.87:1 on white, too faint to read comfortably. The fade is also the only sign, so a screen reader reads the line just as it reads one that is included.
05

Verify the fix

4 checks, no mouse.

Test with: Screen reader, Zoom

0 of 4 checked

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat whenever the icon library, its version or the shared cell component changes.

Limits

This is a starting pattern, not a guarantee for every table. Screen readers differ in what they say for an empty cell and in how they read an image inside a cell, so test with the assistive technology your users have. The words in a cell only help when the cell also has its headers: a value read as "Included" needs its plan and its feature, and a comparison table drawn with div elements or with bold text for headers fails there, as data tables with headers that are only bold text shows. For icons outside a table, naming them and hiding the decorative ones is in SVG icons with no name, or read when they should be silent, and icons inside buttons are in icon-only buttons with no accessible name.

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

EaseWeb service

Fixed it? Keep it from coming back.

I turn guides like this one into rules your coding agents follow and checks your CI runs. Then I retest by hand with a keyboard and screen readers, periodically.

See the service