Skip to content
easeweb
Search topics

Seat maps keyboards can't use and screen readers can't read

Each seat is an empty div that takes only a click, or a button with no name, and free, taken and chosen seats differ only in colour.

WCAG 2.2
SC 1.4.1ASC 2.1.1ASC 4.1.2A
Required by
Section 508 · EN 301 549 (EU)
Broken <div class="seat taken"></div>
The accessibility problem illustrated: No vision:Which seats are free?
01

The problem

Keyboard users can't choose a seat, screen reader users can't tell which seat is which or whether it is free, and people who don't see red and green apart can't tell free seats from taken ones

02

Try it

Using only the keyboard, choose two free seats side by side in row C

  • Broken 1: press Tab. Focus goes past every seat to Continue, and no seat is read. Turn on the simulation: the free and taken seats look alike.

  • Broken 2: the same seats as buttons. Tab stops on each one, but every seat is just "button", and choosing one changes only its colour.

  • Apply a fix. With the checkboxes, Tab moves through the free seats and Space chooses one. In the grid, one Tab enters the map and the arrow keys move between seats and rows.

Broken Can you fix this?

Choose your seats

Rows A–B $10 · Rows C–D $14

  • Free
  • Chosen
  • Taken
Screen
A
B
C
D

Screen reader says:

(Tab to the seats)

A recreated demo. The broken version is intentionally inaccessible.

03

The fix

Name each seat, reach it by keyboard, and mark its state

Before

Seats as divs that take a click

<h2>Choose your seats</h2><p>Rows A–B $10 · Rows C–D $14</p><ul class="legend">  <li>    <span class="key"></span>    Free  </li>  <li>    <span class="key chosen"></span>    Chosen  </li>  <li>    <span class="key taken"></span>    Taken  </li></ul><div class="seat-map">  <div class="screen">Screen</div>  …  <div class="row">    <span class="row-name">C</span>    <div class="seat"></div>    <div class="seat"></div>    <div class="seat taken"></div>    <div class="seat taken"></div>    <div class="seat"></div>    <div class="seat"></div>  </div>  …</div><button type="button" class="continue">Continue</button>
What is wrong4 points
  • The seats answer only click and take no focus, so Tab goes past the map and no seat can be chosen from the keyboard.
  • Each seat is an empty div, so a screen reader reads the row letters and nothing between them.
  • Free, taken and chosen are classes, so nothing tells assistive technology which is which.
  • On screen, the fill colour is the only difference between them.
After

A checkbox for each seat

<h2>Choose your seats</h2><p>Rows A–B $10 · Rows C–D $14</p><ul class="legend">  <li>    <span class="key"></span>    Free  </li>  <li>    <span class="key chosen"></span>    Chosen  </li>  <li>    <span class="key taken"></span>    Taken  </li></ul><div class="seat-map">  <div class="screen">Screen</div>  …  <div class="row">    <span class="row-name">C</span>    <label class="seat">      <input type="checkbox" name="seats" value="C1">      <span class="visually-hidden">Row C, seat 1, $14</span>    </label>    <label class="seat">      <input type="checkbox" name="seats" value="C2">      <span class="visually-hidden">Row C, seat 2, $14</span>    </label>    <label class="seat">      <input type="checkbox" name="seats" value="C3" disabled>      <span class="visually-hidden">Row C, seat 3, $14</span>    </label>    <label class="seat">      <input type="checkbox" name="seats" value="C4" disabled>      <span class="visually-hidden">Row C, seat 4, $14</span>    </label>    <label class="seat">      <input type="checkbox" name="seats" value="C5">      <span class="visually-hidden">Row C, seat 5, $14</span>    </label>    <label class="seat">      <input type="checkbox" name="seats" value="C6">      <span class="visually-hidden">Row C, seat 6, $14</span>    </label>  </div>  …</div><button type="button" class="continue">Continue</button>
How it is fixed5 steps
  1. Make each seat a checkbox inside a label, with hidden text that gives its row, number and price. Tab stops on it, Space chooses it, and a screen reader says "Row C, seat 5, $14, checkbox, not checked".
  2. Disable the checkbox of a taken seat. Tab passes it, and a screen reader reading through the map announces it as unavailable or dimmed.
  3. Draw the seat on the checkbox itself with appearance: none, and its colour from :checked and :disabled, so the look can't drift from what is announced.
  4. Add a tick to a chosen seat and a cross to a taken one, in the seats and in the key, drawn with borders so that they also show in a Windows contrast theme.
  5. Delete the script. The checkbox keeps its own state, and inside a form, the values of the chosen seats are sent with no code.

This fixes both Befores and passes 1.4.1, 2.1.1 and 4.1.2. Every free seat is a Tab stop, in reading order, row by row.

Why this fix: Use native HTML first

04

Verify the fix

5 checks, no mouse.

Test with: Keyboard, Screen reader, Colour vision simulation, Forced colors

0 of 5 checked

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the seat map, its component or its library changes.

How screen readers handle aria-pressed and role="grid", a button in each cell

Limits

This is a starting pattern, not a guarantee for every application. The grid's script is a minimal sketch: it has no Page Up and Page Down, and no way to jump to a row by its letter, which a large venue may need. NVDA has been reported to leave focus mode when the arrow keys move to a link in a grid cell, after which the arrows move its reading cursor instead; if it does the same with these buttons, NVDA users need Insert + Space to get the arrow keys back, so test the grid with NVDA in particular. A venue drawn on a street map, such as a list of cinemas, is covered in maps that are the only way to find a location. A grid whose cells are edited, rather than chosen, is covered in editable data grids a keyboard can't move through or edit, and checkboxes drawn by hand in a form in custom checkboxes that keyboards and screen readers skip. Test the complete journey, from choosing a showing to paying, with your target assistive technology.

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