WCAG 1.3.1 · Level A · EN 301 549 9.1.3.1

Info and Relationships

Requires that structure and relationships shown visually, such as headings, lists, tables, form labels and groups, are also available to assistive technology through code or text.

In brief

A sighted user sees at a glance that a large bold line is a heading, that aligned items form a list, that a label belongs to a field and that a grid of numbers is a table. A screen reader user sees none of this unless the page says it in code.

This criterion requires that information, structure and relationships that are conveyed through presentation can also be determined programmatically or are available in text. In practice this means using real headings, lists, tables, labels and groups, instead of styling plain elements so they merely look like them.

What does it cover?

  • Headings and sections: Visual headings are marked up as headings, at the right level. Regions such as navigation, main content and footer are marked as landmarks.
  • Lists: Items that look like a list are coded as a list, so the number of items and the position are announced.
  • Data tables: Header cells are marked as headers and associated with the data cells they describe. A caption names the table.
  • Form labels and groups: Every field has a programmatic label. Related controls, such as a set of radio buttons, are grouped with a name for the group.
  • Other visual cues: Required fields, current page in a menu, selected tab, and emphasis that carries meaning are available to assistive technology, not only as a color or a shape.
  • Out of scope: The order of content is covered by 1.3.2, name, role and value of controls by 4.1.2, labels and instructions in forms by 3.3.2, and headings and labels that describe purpose by 2.4.6.

Who does it affect?

Screen reader users navigate by headings, landmarks, lists and tables, and depend on the code to know what each thing is. People with low vision who use custom styles or reader modes, and people who use voice control, rely on real labels and structure too. Clear structure also helps people with cognitive differences and search engines.

In the EAA and EN 301 549

The European Accessibility Act (Directive (EU) 2019/882) applies to in-scope products and services placed on the market after 28 June 2025. Recital 47 names four principles for websites and mobile applications: perceivable, operable, understandable and robust. Structure that assistive technology can read is part of "perceivable" and "robust".

The technical counterpart is the standard EN 301 549, which incorporates WCAG 1.3.1 by reference and turns it into separate clauses for each kind of ICT.

Where WCAG 1.3.1 appears in EN 301 549
ClauseType of ICTWhat it requires
9.1.3.1Web pagesWeb content must satisfy WCAG success criterion 1.3.1.
10.1.3.1Non-web documents (PDF, Office files)The same criterion applies to the structure of documents (tags in PDF, styles in Office files).
11.1.3.1Non-web software (native mobile apps)Software that supports screen readers must satisfy the criterion.

Clause numbers follow the "9. + WCAG number" pattern of EN 301 549. In V3.2.1 the software clause is divided into further subclauses for open and closed functionality. Check the exact numbers in the standard when you cite them.

Standard version: EN 301 549 V4.1.1 (September 2026) is based on WCAG 2.2 and is the first version prepared specifically for the EAA. It has not yet been cited in the Official Journal of the European Union, so for now it is best treated as a voluntary technical route to the EAA's requirements. Once cited, it will give a presumption of conformity. The text of criterion 1.3.1 is the same in WCAG 2.1 and 2.2.

A note on EAA scope: Article 2(4) of the Directive excludes certain content from the requirements, for example office file formats published before 28 June 2025 and archives that are not updated after that date. Content you publish or change after that date is not covered by these exclusions.

Directive (EU) 2019/882, EUR-Lex, opens in a new tab

Code examples for the web

1. Headings

Use heading elements for headings, in a logical order. Do not simulate them with large, bold text.

Incorrect
<div class="big-title">Pricing</div>
<p class="bold-line">Monthly plans</p>
Correct
<h1>Pricing</h1>
<h2>Monthly plans</h2>

2. Lists

A set of related items is a list. A screen reader then announces "list, 3 items".

Incorrect
<p>• Fast setup<br>
• No contract<br>
• Free support</p>
Correct
<ul>
  <li>Fast setup</li>
  <li>No contract</li>
  <li>Free support</li>
</ul>

3. Data tables

Mark header cells with th and a scope, and name the table with a caption.

Incorrect
<table>
  <tr><td><b>Plan</b></td><td><b>Price</b></td></tr>
  <tr><td>Basic</td><td>€9</td></tr>
</table>
Correct
<table>
  <caption>Plans and prices</caption>
  <thead>
    <tr><th scope="col">Plan</th><th scope="col">Price</th></tr>
  </thead>
  <tbody>
    <tr><th scope="row">Basic</th><td>€9</td></tr>
  </tbody>
</table>

4. Form labels

A label that is only placed next to the field is not connected to it. Connect them with label for.

Incorrect
<span>Email</span>
<input type="email" id="email">
Correct
<label for="email">Email</label>
<input type="email" id="email">

5. Grouped controls

Give a group of related controls, such as radio buttons, a name with fieldset and legend.

Incorrect
<p>Delivery method</p>
<input type="radio" name="d" id="d1"> <label for="d1">Courier</label>
<input type="radio" name="d" id="d2"> <label for="d2">Pickup</label>
Correct
<fieldset>
  <legend>Delivery method</legend>
  <input type="radio" name="d" id="d1">
  <label for="d1">Courier</label>
  <input type="radio" name="d" id="d2">
  <label for="d2">Pickup</label>
</fieldset>

6. Landmarks

Mark the main regions so screen reader users can jump between them. If there is more than one navigation region, name each one.

Incorrect
<div class="nav">…</div>
<div class="content">…</div>
<div class="footer">…</div>
Correct
<header>…</header>
<nav aria-label="Main">…</nav>
<main>…</main>
<footer>…</footer>

Code examples for mobile

The same rule applies in native mobile apps. Mark headings as headings, join a label and its value into one element, and give every field a label.

iOS (SwiftUI)

import SwiftUI

struct AccountView: View {
    @State private var email = ""

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            // A heading, announced as a heading
            Text("Account details")
                .font(.title2)
                .accessibilityAddTraits(.isHeader)

            // A label and its value read as one item
            HStack {
                Text("Plan")
                Spacer()
                Text("Business")
            }
            .accessibilityElement(children: .combine)

            // The field has a label ("Email")
            TextField("Email", text: $email)
                .textFieldStyle(.roundedBorder)
        }
        .padding()
    }
}

Android (Jetpack Compose)

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics

@Composable
fun AccountScreen() {
    var email by remember { mutableStateOf("") }

    Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
        // A heading, announced as a heading
        Text(
            text = "Account details",
            style = MaterialTheme.typography.titleLarge,
            modifier = Modifier.semantics { heading() }
        )

        // A label and its value read as one item
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .semantics(mergeDescendants = true) {},
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            Text("Plan")
            Text("Business")
        }

        // The field has a label
        OutlinedTextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") }
        )
    }
}

How to test

  • Turn off the styles: Disable CSS, or view the page in a reader mode. Do the headings, lists and tables still look like headings, lists and tables? Is the order and grouping still clear?
  • Navigate by structure: With NVDA, VoiceOver or TalkBack, jump through headings, landmarks, lists and tables. Does the outline make sense without looking at the page?
  • Check the code: Are visual headings real h1 to h6 elements? Are lists ul, ol or dl? Do tables use th, scope and caption? Is every field connected to a label?
  • Listen to a form: When focus moves to a field, does the screen reader say its label? When it enters a group, does it say the group name?
  • Check cues that are only visual: Required fields, the current page and a selected tab: is each also available as text or as a state, not just as a color?
  • Use a checker as a start: Automated tools find missing labels, empty headings and table markup problems. They cannot tell whether a heading level or a grouping is correct. Only a person can decide that.

Common mistakes

  • Faking headings with styles: A bold, large div is not a heading. It does not appear in the heading outline.
  • Skipping heading levels or choosing them for looks: Choose the level for the structure, and use CSS for the size.
  • Using a table for layout: Layout tables confuse screen readers. Use CSS layout and keep tables for data.
  • Using th only for looks: Header cells that do not describe data cells mislead users.
  • Placeholder text instead of a label: The placeholder disappears when typing and is not a reliable label.
  • Leaving radio buttons and checkboxes ungrouped: Users hear the options, but not the question they answer.
  • Using only a color or icon to show a state: Required, error or current state must also be in text or a programmatic state.
  • Writing lists with line breaks and symbols: A screen reader does not know it is a list.

Sources

Standard version: EN 301 549 V4.1.1 (2026-09), WCAG 2.2. This page is for informational purposes only and is not legal advice. For binding requirements, refer to the official texts of the European Accessibility Act (Directive (EU) 2019/882) and EN 301 549.

Corpowid is recognized by Gartner

Corpowid has been recognized by Gartner, a leading global research and advisory firm, for our innovation and performance in digital accessibility. These badges reflect our commitment to creating inclusive, AI-powered web experiences.

Have questions about Corpowid?

Let’s connect.

We will get back to you as soon as possible.