Html accessibility checklist

Summarize this post with AI ChatGPT OR

Table of Contents

HTML Accessibility Checklist: Landmarks, ARIA & Keyboard

HTML accessibility checklist is the list you run through before you call a page done: landmarks that map the page, ARIA used only where native HTML falls short, keyboard navigation that reaches everything a mouse can reach, alt text that says something useful, and a focus order that follows the visual order. This guide turns that list into checks you can actually perform, with the code for each fix shown as a complete document you can run.

Accessibility is often presented as a specialist topic, but most of it is plain good HTML. A page built with real headings, real buttons, real labels, and real landmarks is already most of the way accessible — because those elements carry meaning that browsers, screen readers, and keyboards understand for free. The checklist below catches the places where that meaning goes missing, and shows how to put it back.

Quick Takeaways

  • Use landmarks (header, nav, main, aside, footer) so assistive technology can jump between page regions.
  • Follow the first rule of ARIA: do not use ARIA when a native HTML element does the job.
  • Everything clickable must be keyboard-operable, with a visible focus indicator and a logical tab order.
  • Every image needs a decision: meaningful alt text, or empty alt (alt="") for decoration.
  • Every form control needs a real <label>; placeholders are not labels.
  • Text needs contrast of at least 4.5:1 against its background (3:1 for large text).
  • Never rely on color alone to communicate information, and never remove focus outlines without replacing them.
  • Test by keyboard alone, at 200% zoom, and with a screen reader smoke test — automated checkers catch only part of the list.

1. What Is Web Accessibility?

Web accessibility is the practice of building pages that people with disabilities can perceive, operate, and understand. That includes people who cannot use a mouse, people who cannot see the screen, people who cannot hear audio, people with cognitive disabilities, and people in temporary situations — a broken arm, bright sunlight, a slow connection — that mimic those conditions.

The standard behind most accessibility work is the Web Content Accessibility Guidelines (WCAG), organized around four principles: content must be perceivable, operable, understandable, and robust. You do not need to memorize WCAG to use this checklist. Each section below maps to one of those principles in plain terms, with the HTML that satisfies it.

One mindset shift matters more than any single technique: accessibility is not a layer you add at the end. It is a property of the markup you choose at the start. A <button> is accessible in ways a <div onclick> never will be, no matter how much ARIA you pile onto the div. Choose the right element first, and most of the checklist takes care of itself.

2. Landmarks: Give the Page a Map

2.1 What landmarks are

Landmarks are the regions of a page that assistive technology can list and jump between: the banner, the navigation, the main content, complementary content, and the footer. Screen reader users commonly pull up a landmarks list as the first thing they do on an unfamiliar page, the way sighted users scan a layout. A page with no landmarks is a page with no map.

2.2 The landmark elements

ElementLandmark roleUse it for
<header>banner (when page-level)Site header, logo, top-level intro
<nav>navigationA block of navigation links
<main>mainThe page’s primary content — exactly one per page
<aside>complementarySidebars, pull quotes, related content
<footer>contentinfoFooter, copyright, secondary links
<form role="search">searchSite search form

2.3 Landmark rules that catch most mistakes

First, exactly one <main> per page, wrapping the content that is unique to that page — not the header, not the navigation, not the footer. Second, every substantial block of links gets a <nav>; a footer full of links can be a <nav> too, and when a page has more than one navigation block, give each an aria-label (aria-label="Primary", aria-label="Footer") so they are distinguishable. Third, do not nest landmarks inside each other in ways that confuse the map — a <header> inside an <article> is a section header, not a banner, and screen readers treat it accordingly.

2.4 Complete example: a landmarked page skeleton

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Landmarked Page Skeleton</title>
</head>
<body>
  <header>
    <p>My Site</p>
    <nav aria-label="Primary">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/guides">Guides</a></li>
      </ul>
    </nav>
  </header>
  <main>
    <h1>Page title</h1>
    <p>The content unique to this page goes here.</p>
  </main>
  <aside>
    <h2>Related reading</h2>
    <p>Complementary content goes here.</p>
  </aside>
  <footer>
    <nav aria-label="Footer">
      <ul>
        <li><a href="/privacy">Privacy</a></li>
      </ul>
    </nav>
  </footer>
</body>
</html>

3. Headings and Page Structure

3.1 One H1, then a real hierarchy

Every page needs exactly one <h1> stating the page’s topic, followed by <h2> sections, <h3> subsections, and so on, without skipping levels. Screen reader users navigate by headings the way sighted users scan them — a page that jumps from <h1> to <h4> reads like a book with missing chapters.

3.2 Headings are structure, not styling

Never pick a heading level because of how big it looks. If an <h3> looks right but the structure calls for an <h2>, use the <h2> and change its size with CSS. Font size is a styling decision; heading level is a meaning decision, and assistive technology trusts the meaning.

3.3 Page title and language

Two small items that belong in every audit: the <title> should describe the page specifically (not just the site name), and the <html> element needs a lang attribute (<html lang="en">) so screen readers pronounce content in the right language. Both are one-line fixes that audits flag constantly.

4. ARIA Roles and Attributes: Use Sparingly, Use Correctly

4.1 The first rule of ARIA

The first rule of ARIA is blunt: if a native HTML element can do the job, use it instead of ARIA. A <button> already has the button role, keyboard support, and focus behavior built in. A <div role="button" tabindex="0"> needs all of that rebuilt by hand — including Enter and Space key handling — and hand-built versions almost always miss something. ARIA fills gaps in native HTML; it is not a replacement for it.

4.2 ARIA worth knowing

A small set of ARIA attributes covers most legitimate uses:

  • aria-label — gives an accessible name when no visible text exists, for example an icon-only button: <button aria-label="Close">×</button>.
  • aria-labelledby — points at visible text that names the element, for example a dialog labelled by its heading.
  • aria-expanded — tells assistive technology whether a collapsible section or menu is open (true) or closed (false); update it whenever the state changes.
  • aria-describedby — links an element to extra descriptive text, such as a password hint or an error message.
  • aria-live — marks a region whose updates should be announced, such as a form status message (aria-live="polite" for non-urgent updates).

4.3 ARIA mistakes that make things worse

Three mistakes appear in audit after audit. First, aria-hidden="true" on a focusable element hides it from screen readers while leaving it keyboard-reachable — a focus target that announces nothing. Second, redundant ARIA: role="button" on a real <button>, or role="navigation" on a <nav>, adds noise and, in some cases, overrides correct native behavior. Third, ARIA that lies: an aria-expanded="false" that never updates when the menu opens teaches assistive technology to distrust the page. ARIA must always match reality, or it is worse than nothing.

5. Keyboard Navigation: Everything Must Work Without a Mouse

5.1 The keyboard-only test

Put the mouse aside and use only Tab, Shift+Tab, Enter, Space, and arrow keys. Can you reach every link, button, menu, and form control? Can you operate every custom widget? Can you tell where focus is at all times? If any answer is no, the page fails keyboard accessibility, and a significant group of users cannot use it at all.

5.2 Visible focus is non-negotiable

The focus indicator — usually an outline around the focused element — is how keyboard users know where they are. Removing it with outline: none and providing nothing in its place is one of the most common and most damaging accessibility mistakes. If the default outline clashes with your design, replace it with a custom style (:focus-visible with a clear outline or border), but never remove it outright.

5.3 Tab order and tabindex

Tab order should follow the visual and logical order of the page. Two tabindex rules prevent most problems: use tabindex="0" to make a custom element focusable in natural order, and tabindex="-1" to make an element focusable only programmatically (for example, moving focus into a dialog). Never use positive tabindex values (tabindex="1", tabindex="2") — they hijack the natural order and create tab sequences that jump around the page unpredictably.

5.4 Focus management in dialogs

When a dialog opens, move focus into it; while it is open, keep focus inside it; when it closes, return focus to the element that opened it. A dialog that leaves focus wandering behind the overlay traps keyboard users in the worst way: they can see the dialog but cannot reach it. Native <dialog> handles much of this, which is one more reason to prefer native elements.

6. Images and Alt Text

6.1 Every image needs a decision

Every <img> needs either meaningful alt text or an explicit decision that it is decorative. There is no third option — a missing alt attribute leaves assistive technology guessing, and different tools guess differently.

6.2 Writing useful alt text

Good alt text says what the image communicates, not what it looks like in photographic detail. For a chart, that means the trend or conclusion, not “a bar chart with blue and red bars.” For a functional image (a linked logo, an icon button), the alt text says what happens when you activate it (“Home”, “Search”), not what the icon depicts. Keep it concise: if the description needs more than a sentence or two, put the long description in nearby text and keep the alt short.

6.3 Decorative images

Purely decorative images — dividers, background flourishes, stock photos that add no information — get an empty alt attribute, alt="". That is not the same as missing alt: empty alt explicitly tells assistive technology to skip the image. CSS background images are decorative by nature and need no alt handling at all, which is one reason to prefer CSS for decoration.

7. Forms and Labels

7.1 Labels are mandatory

Every form control needs a <label> associated with it, either by wrapping the control or by matching for and id. A label is what screen readers announce when focus lands on a control; without one, a user hears “edit text, blank” with no idea what the field is for. Placeholders are not labels: they disappear when the user types, they are often low-contrast, and many assistive tools do not announce them as names.

7.2 Errors must be identified in text

When a form submission fails, say so in text, name the fields with problems, and ideally move focus or link to the first error. An error shown only by turning a border red fails everyone who cannot perceive that color change — the same color-alone rule from the contrast section, applied to forms.

7.3 Group related controls

Related controls belong in a <fieldset> with a <legend> describing the group — a set of radio buttons for a delivery method, for example. The legend is announced with each control in the group, which is the difference between hearing “Standard, radio button” and hearing “Delivery method: Standard, radio button.”

7.4 Complete example: an accessible form

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Accessible Form Example</title>
</head>
<body>
  <main>
    <h1>Contact us</h1>
    <form action="/contact" method="post">
      <p>
        <label for="name">Full name</label><br>
        <input type="text" id="name" name="name" autocomplete="name" required>
      </p>
      <p>
        <label for="email">Email address</label><br>
        <input type="email" id="email" name="email" autocomplete="email" required>
      </p>
      <fieldset>
        <legend>Preferred contact method</legend>
        <p>
          <input type="radio" id="by-email" name="contact-method" value="email" checked>
          <label for="by-email">Email</label>
        </p>
        <p>
          <input type="radio" id="by-phone" name="contact-method" value="phone">
          <label for="by-phone">Phone</label>
        </p>
      </fieldset>
      <p><button type="submit">Send message</button></p>
    </form>
  </main>
</body>
</html>

8. Color, Contrast, and Motion

8.1 Contrast ratios to remember

Normal text needs a contrast ratio of at least 4.5:1 against its background; large text needs 3:1. Logos and purely decorative text are exempt, but body copy never is. Light grey text on white is the classic failure — it looks refined in a mockup and vanishes in sunlight or on a dim screen.

8.2 Never color alone

Color must never be the only channel carrying information. A required field marked only by a red border, an error shown only in red text, or a chart whose series differ only by hue all fail users who cannot distinguish those colors. Pair color with text, an icon, or a pattern, every time.

8.3 Motion and animation

Respect users who experience motion sensitivity: avoid autoplaying, flashing, or large parallax movement, and honor the prefers-reduced-motion media query by disabling non-essential animation for users who request it. Content that flashes more than three times per second is not just annoying — it can trigger seizures, and WCAG addresses it directly.

9. Focus Order, Skip Links, and Page Titles

9.1 Skip links save time

A “Skip to main content” link as the first focusable element lets keyboard and screen reader users bypass repeated navigation on every page. It can be visually hidden until focused, so it costs sighted mouse users nothing and saves keyboard users dozens of Tab presses per page.

9.2 Complete example: skip link in action

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Skip Link Example</title>
<style>
  .skip-link {
    position: absolute;
    left: -9999px;
  }
  .skip-link:focus {
    position: static;
  }
</style>
</head>
<body>
  <a class="skip-link" href="#main">Skip to main content</a>
  <header>
    <nav aria-label="Primary">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/guides">Guides</a></li>
      </ul>
    </nav>
  </header>
  <main id="main">
    <h1>Page title</h1>
    <p>Keyboard users land here directly with the skip link.</p>
  </main>
</body>
</html>

9.3 Descriptive link text

Link text should make sense out of context. “Click here” and “read more” tell a screen reader user — who often pulls up a list of all links on a page — nothing about where each link goes. Write “Read the HTML headings guide” instead of “Click here to read more.” The same rule applies to buttons: “Send message” beats “Submit” when several forms share a page.

10. Testing Your Page: The Checklist in Practice

10.1 The five-minute manual test

Run this on every page before you publish: (1) navigate the whole page by keyboard alone; (2) zoom to 200% and check nothing overlaps or disappears; (3) turn images off or read the alt text and check the page still makes sense; (4) check every form control has a visible label; (5) tab through and confirm the focus indicator is always visible. Five minutes catches most failures that automated tools miss.

10.2 Screen reader smoke test

You do not need to become a screen reader expert to smoke-test a page. Turn on a free screen reader (NVDA on Windows, VoiceOver on Mac), navigate by headings and landmarks, and listen: does the page’s structure make sense? Do buttons announce their purpose? Do images announce something useful or stay silent when decorative? A ten-minute listen finds problems no automated scan can describe.

10.3 Automated checkers help, but do not finish the job

Automated accessibility checkers catch real issues — missing alt attributes, missing labels, low contrast, invalid ARIA — and they belong in every workflow. But they catch roughly a third of WCAG issues at most: they cannot judge whether alt text is meaningful, whether tab order is logical, or whether a custom widget is actually operable. Treat a clean automated report as a starting point, never as proof of accessibility.

11. Accessible Tables, Lists, and Media

11.1 Tables need real headers

A data table is only accessible if its headers are marked as headers. Use <th> for header cells (not bolded <td> cells), add scope="col" for column headers and scope="row" for row headers, and give the table a <caption> that summarizes what it contains. Screen readers use that structure to announce each data cell with its headers — “Price: $24” instead of just “$24” with no context. Layout tables built from divs or from tables used for page layout throw all of that away; use CSS layout instead, and reserve <table> for actual data.

11.2 Lists keep their meaning

Use real <ul>, <ol>, and <li> elements for lists instead of lines of text separated by breaks or dashes. A screen reader announces “list, five items” and lets users jump between items; a pile of <br>-separated lines announces as one undifferentiated paragraph. The same applies to navigation: a <nav> containing a <ul> of links is a structure assistive technology understands, while a row of bare links is not.

11.3 Media needs captions and transcripts

Video needs captions for users who cannot hear it, and the native way to provide them is the <track> element with a WebVTT file: <track kind="captions" src="captions.vtt" srclang="en" label="English">. Audio-only content needs a transcript — a text version of everything spoken, linked near the player. Both are small amounts of work compared with producing the media itself, and both make that media available to audiences who would otherwise get nothing from it.

11.4 Complete example: an accessible data table

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Accessible Table Example</title>
</head>
<body>
  <main>
    <h1>Workshop prices</h1>
    <table>
      <caption>Workshop prices per person, including materials.</caption>
      <thead>
        <tr>
          <th scope="col">Workshop</th>
          <th scope="col">Duration</th>
          <th scope="col">Price</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">HTML basics</th>
          <td>One day</td>
          <td>$99</td>
        </tr>
        <tr>
          <th scope="row">CSS layout</th>
          <td>Two days</td>
          <td>$179</td>
        </tr>
      </tbody>
    </table>
  </main>
</body>
</html>

12. Common Mistakes on the Accessibility Checklist

12.1 Divs pretending to be buttons

A <div> with a click handler is not a button: it has no button role, no keyboard support, and no focus behavior unless all three are rebuilt by hand. Use <button>. The same applies to links: if it navigates, it is an <a>; if it performs an action, it is a <button>.

12.2 Placeholders as labels

A placeholder that vanishes when the user types cannot serve as a label — the user loses the field’s purpose exactly when they need it. Keep visible labels, and use placeholders only for short hints or examples.

12.3 Positive tabindex values

tabindex="1" and friends override the natural tab order and create sequences that jump around the page. Use tabindex="0" for natural order and tabindex="-1" for programmatic focus only.

12.4 Hiding focusable content with aria-hidden

aria-hidden="true" on an element that can still receive focus creates a focus target that screen readers cannot see. Never combine the two; if something is hidden from assistive technology, remove it from the tab order too.

12.5 Autoplaying media and motion

Autoplaying video with sound, and large animated effects that cannot be paused, fail operability and safety checks at once. Do not autoplay sound, provide pause controls for motion, and respect prefers-reduced-motion.

Frequently Asked Questions

1. Is accessibility only about screen readers?

No. Screen readers are one group among many: keyboard-only users, voice-control users, users with low vision or color blindness, users with cognitive disabilities, and users with motor disabilities all depend on different parts of this checklist. A page that works for screen readers but not keyboards is still inaccessible.

2. Do I need to follow all of WCAG?

WCAG is the reference, but this checklist covers the failures that appear most often in real audits: landmarks, headings, ARIA misuse, keyboard support, labels, alt text, contrast, and focus. Fixing those first removes the large majority of barriers; WCAG conformance is the longer road beyond it.

3. When should I use ARIA at all?

When native HTML cannot express what you built: a custom tab interface, a tree view, a live-updating status region, or a composite widget with no native equivalent. In those cases ARIA is essential — and it must be implemented fully, including keyboard behavior and state updates, not just roles pasted onto divs.

4. Does semantic HTML really help SEO too?

Yes, and for the same reason it helps accessibility: search engines, like screen readers, understand structure. Real headings, landmarks, and descriptive link text give search engines the same map they give assistive technology. Accessibility and SEO overlap far more than most developers expect.

5. How do I test accessibility without being an expert?

The five-minute manual test in section 10 catches most issues: keyboard-only navigation, 200% zoom, images off, labels present, focus always visible. Add a screen reader smoke test and an automated checker, and you have a testing routine that beats most professional audits’ first pass.

6. What is the single highest-impact accessibility fix?

Use native elements: buttons for actions, links for navigation, labels for controls, headings for structure, landmarks for regions. One habit — choosing the right element instead of a div — prevents more accessibility failures than any other single change.

Conclusion

An HTML accessibility checklist is not a list of exotic techniques. It is a discipline of choosing meaningful elements, labelling everything, keeping everything keyboard-reachable, and testing the result the way your users will experience it. Landmarks give the page a map, ARIA fills only the gaps native HTML leaves, keyboard support makes the page operable, and contrast and labels make it perceivable. Run the five-minute manual test on your next page before you publish it, and fix what it finds — that single habit will put your pages ahead of most of the web.

Your next step: take one page you already published, run the keyboard-only test on it, and fix the first failure you find. Then run the checklist again. Accessibility improves fastest one real fix at a time.

Related Articles You’ll Love

Authoritative reference: Web Accessibility — MDN

No comment

Leave a Reply

Your email address will not be published. Required fields are marked *