Chapter 1 of 8 · 6 checks · 4 min
Structure and semantics
Screen reader users move through a page by its headings, landmarks and lists. These checks make sure the structure in the code matches the structure people see.
Set the page language on the html element (SC 3.1.1)Must
Why it matters and how to check
A missing
langattribute is one of the six most common failures in the WebAIM Million 2026 report, found on 13.5% of home pages. Without it, a screen reader guesses the language and may read English text with a French voice, or the other way round. Setlangon thehtmlelement, and set it again on any passage in a different language.To verify, view the page source and confirm the
htmlelement has a valid code such aslang="en"orlang="ur". In a multi-language app, switch the interface language and check the attribute changes with it.Example
HTML <html lang="en"> ... <p>The French word <span lang="fr">bonjour</span> means hello.</p> </html>Give every page a unique, descriptive title (SC 2.4.2)Must
Why it matters and how to check
The page title is the first thing a screen reader announces and the label of the browser tab. "Home" on every page, or the app name alone, tells nobody where they are. Put the specific page first and the site name last, for example
Edit profile | Acme. In a single page app, updatedocument.titleon every route change.To verify, open five different pages, including a form step and an error page, and read the tab titles. Each should be different and say what the page is for. In a single page app, navigate with the in-app links, not reloads, and confirm the title follows.
Use one h1 and a heading order that matches the visual layout (SC 1.3.1, 2.4.6)Should
Why it matters and how to check
Many screen reader users jump from heading to heading to find what they want. Headings must be real
h1toh6elements, not bold paragraphs, and their levels should describe the outline: a section under anh2is anh3. Do not pick a heading level for its font size; style it with CSS instead.To verify, run a heading outline tool such as the axe DevTools or WAVE browser extension, or the rotor in VoiceOver, and read the list on its own. It should read like a table of contents for the page, with no skipped levels and no visual headings missing from it.
Avoid
- Using a heading tag just to make text big and bold
- Styling a
divto look like a heading
Mark up page regions with landmark elementsShould
Why it matters and how to check
Landmarks let assistive technology users jump straight to the main content, the navigation or the footer. Use
header,nav,main,asideandfooterinstead of plaindivelements, with exactly onemainper page. If you have more than onenav, give each anaria-labelsuch as "Primary" and "Breadcrumb" so they can be told apart.To verify, open the landmarks list in your screen reader (the rotor in VoiceOver, or the D key in NVDA) or use a landmarks browser extension. All visible content should sit inside a landmark, and every repeated landmark type should have a distinct label.
Provide a skip link to the main content (SC 2.4.1)Should
Why it matters and how to check
Keyboard users otherwise tab through the whole header and menu on every page before reaching the content. A skip link is the first focusable element on the page, can be visually hidden until it receives focus, and moves focus to the
mainelement.To verify, load a page, press Tab once and confirm a visible "Skip to main content" link appears. Press Enter and Tab again: focus should land on the first interactive element inside the main content, not back in the header.
Example
HTML <a class="skip-link" href="#main">Skip to main content</a> ... <main id="main" tabindex="-1">...</main>Use native buttons, links and inputs instead of clickable divs (SC 4.1.2)Must
Why it matters and how to check
A
divwith a click handler is invisible to the keyboard and silent to a screen reader. Abuttongets focus, Enter and Space activation, a role and a disabled state for free. Use a link when the action goes somewhere and a button when it does something on the page.To verify, search your components for
onClickondiv,spanandlielements. Each one is either a bug or needs the full button behaviour added by hand. Then tab through the page and confirm every clickable thing is reached and announced with the right role.Avoid
<div onClick>for actions- Links with
href="#"that act as buttons