Skip to content

Learn

1.3.1 Info and Relationships

Structure shown on screen, such as headings, lists, tables and labels, is also in the markup, so assistive technology can convey it.

Level A

What the automated checks look for

Page bodies are hidden from assistive technology

aria-hidden="true" on the body hides the whole page from assistive technology.

Who it affects. A screen reader finds nothing on the page, so blind people can't read or use any of it.

How to fix it. Remove aria-hidden from the body. To hide what's behind a dialog, use the inert attribute on the page's other content.

<body>
  <main inert>…</main>
  <div role="dialog">…</div>
</body>

Custom inputs have no accessible name

A field built from ARIA needs an accessible name, or a screen reader can't say what to enter.

Who it affects. A screen reader announces an edit field or combobox with no name, so blind people don't know what to type or pick.

How to fix it. Name the field with aria-labelledby pointing at its visible label, or use a native input with a label.

<span id="city-label">City</span>
<div role="combobox" aria-labelledby="city-label" aria-expanded="false"></div>

Elements are missing required child roles

A role that must contain certain children (a list its items, a table its rows) is incomplete without them.

Who it affects. A screen reader can't count or step through the items, for example "list, 0 items" or a tab list with no tabs.

How to fix it. Give the parent the child roles it requires, or use the native elements.

<div role="tablist">
  <button role="tab" aria-selected="true">Details</button>
</div>

Elements are missing a required parent role

An item role outside the container it belongs to (a tab outside a tablist) is misreported.

Who it affects. A screen reader can't say how many items there are or which one this is, so blind people lose the structure.

How to fix it. Put the element inside a parent with the role it requires.

<ul role="menu">
  <li role="menuitem">Rename</li>
</ul>

Definition lists are not built correctly

A definition list with the wrong children loses the pairing of terms and definitions.

Who it affects. A screen reader can't pair each term with its value, so blind people hear a jumble of words.

How to fix it. Put only dt and dd elements, optionally grouped in div, directly inside a dl.

<dl>
  <dt>Due</dt>
  <dd>25 September 2026</dd>
</dl>

Definition items are outside a definition list

A term or definition outside a definition list loses its pairing.

Who it affects. A screen reader can't tell that the text is a term and its value.

How to fix it. Put every dt and dd inside a dl.

<dl>
  <dt>Plan</dt>
  <dd>Starter</dd>
</dl>

Ids are used more than once

Two elements with the same id can break the label and description relationships that point at them.

Who it affects. A label, description or aria-controls can point at the wrong element, so a screen reader names or describes a field wrongly.

How to fix it. Give every id on the page its own value. In React, a component rendered more than once creates its ids with useId().

<label for="billing-email">Email</label>
<input id="billing-email">

Table headers label no data cell

A table header that labels no data cell, or whose cells name other headers, isn't related to any data.

Who it affects. Moving cell by cell, a screen reader announces the wrong header for the data, or a header with nothing under it.

How to fix it. Give each header the cells it labels: remove empty header columns, and keep a cell's headers attribute in step with the headers above and beside it.

<tr><th id="country">Country</th><th id="capital">Capital</th></tr>
<tr><td headers="country">Zambia</td><td headers="capital">Lusaka</td></tr>

Form fields have no label

A form field with no label is announced without saying what to enter.

Who it affects. A screen reader announces "edit text" with no name, so blind people don't know what to type. Without a label element, clicking the field's name doesn't focus it, so people with limited dexterity have a smaller target.

How to fix it. Add a label element tied to the field with for and id, or wrap the field in the label. A placeholder is not a label.

<label for="email">Email</label>
<input id="email" type="email" name="email">

Lists are not built correctly

A list containing things other than list items is announced with the wrong structure or item count.

Who it affects. A screen reader announces the wrong number of items, or none, so blind people can't tell how long the list is or skip through it.

How to fix it. Put only li elements (or script and template) directly inside ul and ol. Move other wrappers inside the li.

<ul>
  <li><div class="card">…</div></li>
</ul>

List items are outside a list

A list item outside a list loses its structure, so a screen reader can't say it belongs to a list.

Who it affects. A screen reader doesn't say the item is in a list or how many there are.

How to fix it. Put every li inside a ul or ol.

<ul>
  <li>Invoices</li>
  <li>Payments</li>
</ul>

Paragraphs are styled as headings

Text styled to look like a heading isn't a heading to assistive technology.

Who it affects. Screen reader users jump between headings to scan a page, and this one isn't there, so they miss the section.

How to fix it. Use an h1 to h6 at the right level instead of bold or large paragraph text.

<h2>Payment methods</h2>
<!-- not <p><b>Payment methods</b></p> -->

Selects have no accessible name

A select with no label is announced without saying what the choice is for.

Who it affects. A screen reader announces "combo box, Monthly" with no name, so blind people hear the value but not what they are choosing.

How to fix it. Add a label element tied to the select with for and id.

<label for="period">Billing period</label>
<select id="period" name="period">…</select>

Tables use a cell as their caption

A caption made from a table cell isn't announced as the table's caption.

Who it affects. A screen reader reads the title as an ordinary cell, so blind people don't hear what the table is about when they reach it.

How to fix it. Use a caption element as the table's first child.

<table>
  <caption>Invoices due this month</caption>
  …
</table>

Table cells have no header

Data cells in a large table with no headers can't be related to what they mean.

Who it affects. A screen reader reads a number with no column or row name, so blind people can't tell what the value is.

How to fix it. Mark the header row or column with th and scope.

<tr><th scope="col">Month</th><th scope="col">Revenue</th></tr>

Table cells point to headers that do not exist

Cells pointing at headers that don't exist lose their relationship to the table's headers.

Who it affects. A screen reader can't read a cell's headers as someone moves through the table, so blind people lose which column they are in.

How to fix it. Make each id in a cell's headers attribute point at a th in the same table, or use scope on the headers instead.

<th id="amt">Amount</th>
…
<td headers="amt">$120</td>

Table headers have no data cells

A header that labels no cells can't be related to any data.

Who it affects. A screen reader reads a header with nothing under it, and moving cell by cell announces the wrong headers.

How to fix it. Remove empty header columns or rows, or use th only where it labels data cells.

<tr><th scope="col">Invoice</th><th scope="col">Amount</th></tr>
<tr><td>42</td><td>$120</td></tr>

Read more