Skip to content

Plain guides to WCAG, alt text and screen readers

Contrast checker

Accessibility basics

Web accessibility examples: broken and fixed code

Web accessibility examples with broken and fixed code for forms, tables and widgets

  • Code examples
  • WCAG patterns
  • Native HTML first
  • Checked 4 Nov 2026

The most useful web accessibility examples are everyday components done right: an image with sensible alt text, a form field with a real label, a data table with header cells, a dialog that holds keyboard focus, a dropdown that works without a mouse. Each example below shows the broken version auditors find, the fixed code, and the WCAG criteria involved.

Copy the patterns, then try them yourself using only the keyboard, and again with speech output running. A pattern is only accessible once it works in your real page with your real content.

Quick facts

  • Best first fix

    Use native HTML elements: button, select, dialog, table.

  • Most common failures

    Missing alt text, low contrast, unlabelled fields, vague links.

  • Pattern reference

    The W3C guide to ARIA patterns (APG).

  • Test each pattern with

    Keyboard only, then a screen reader, then 400 percent zoom.

  • Rule of thumb

    No ARIA is better than wrong ARIA.

Ten web accessibility examples at a glance

Here are ten digital accessibility examples in one table. The sections after it show code for the trickier ones.

Common component patterns and fixes
PatternWhat usually goes wrongAccessible versionWCAG
Informative imageNo alt, or alt is a file nameShort alt describing what matters1.1.1
Link"Read more" repeated ten timesLink text names the destination2.4.4
Form fieldPlaceholder used as the only labelVisible label tied with for and id3.3.2
Radio buttonsGroup question not tied to optionsfieldset with a legend1.3.1
Data tableHeader row styled but not codedth cells with scope and a caption1.3.1
Dropdowndiv list that only opens on clickNative select element2.1.1
TooltipShows on hover only, cannot be dismissedShows on focus too, closes with Escape1.4.13
DialogFocus stays behind the overlayNative dialog, focus moves in and returns2.4.3
TabsClickable divs with no rolesProper tab roles plus arrow key movement4.1.2
Status message"Added to cart" is silentrole status region4.1.3

Form fields and a radio button group

Forms are where users give up. Every input needs a programmatic label, related controls need a group name, and errors need words, not just a red outline. This is the classic WCAG radio button example:

Fails 1.3.1: the question is plain text, so screen reader users hear only Yes and No.

<p>Send me updates?</p>
<input type="radio" name="up" id="y"> Yes
<input type="radio" name="up" id="n"> No

Passes: the legend is announced with each option.

<fieldset>
  <legend>Send me updates?</legend>
  <label><input type="radio" name="up"> Yes</label>
  <label><input type="radio" name="up"> No</label>
</fieldset>

For errors, write the message beside the input and link the two through aria-describedby, as covered in error identification.

A data table with real headers

A data table needs header cells that are marked up as headers, so a screen reader can say "Plan, Basic" as the user moves through the cells. Use tables only for data, never for page layout.

A WCAG table example that passes 1.3.1:

<table>
  <caption>Delivery times</caption>
  <tr><th scope="col">Zone</th><th scope="col">Days</th></tr>
  <tr><th scope="row">City</th><td>1</td></tr>
  <tr><th scope="row">Rural</th><td>3</td></tr>
</table>

Simple tables only need th with scope. Save headers and id pairs for tables with headers spread across several levels.

Dropdowns and comboboxes

The best WCAG dropdown example is the plain select element. It works with the keyboard, touch and every screen reader with no extra code. Custom dropdowns built from div elements are one of the most common causes of 2.1.1 and 4.1.2 failures.

Native dropdown with a label:

<label for="size">Cup size</label>
<select id="size">
  <option>Small</option>
  <option>Large</option>
</select>

When users must type to filter a long list, you need a combobox. A WCAG combobox example needs a text input with role="combobox", aria-expanded, aria-controls pointing at a listbox, arrow key support and an announced active option. That is a lot of behaviour to get right, so start from the combobox pattern in the ARIA Authoring Practices Guide and test it thoroughly.

<input id="city" role="combobox" aria-expanded="false"
  aria-controls="city-list" aria-autocomplete="list">
<ul id="city-list" role="listbox" hidden></ul>

Tooltips and dialogs

A good WCAG tooltip example appears on keyboard focus as well as hover, is linked to its trigger so it is read aloud, stays visible while the pointer moves onto it, and closes with Escape. That last set of rules is 1.4.13.

Tooltip text tied to the button:

<button aria-describedby="tip1">Share</button>
<span role="tooltip" id="tip1">Copies a link to this page</span>

A good WCAG dialog example pulls focus inside on opening, keeps Tab cycling within, closes on Escape, and hands focus back to whatever launched it. The native dialog element opened with showModal() takes care of most of that.

A labelled modal dialog:

<dialog aria-labelledby="dlg-title">
  <h2 id="dlg-title">Remove item?</h2>
  <button>Remove</button>
  <button>Cancel</button>
</dialog>

Tabs and date pickers

A WCAG tab example uses three roles. The tab list holds the tabs, each tab says whether it is selected, and each panel is labelled by its tab. Arrow keys move between tabs and Tab moves into the panel.

Tabs with roles and state:

<div role="tablist" aria-label="Plans">
  <button role="tab" aria-selected="true"
    aria-controls="p1" id="t1">Monthly</button>
</div>
<div role="tabpanel" id="p1" aria-labelledby="t1">...</div>

For a WCAG calendar example, the safest choice is to let people type the date into a labelled field with the format shown, and offer the calendar grid as an extra. Many users of screen readers and voice control find grid pickers slow. The native input type="date" is a reasonable option where browser support suits your audience.

A typed date with a visible format hint:

<label for="dob">Date of birth</label>
<span id="fmt">Format: DD/MM/YYYY</span>
<input id="dob" aria-describedby="fmt"
  autocomplete="bday" inputmode="numeric">

What accessible websites have in common

When people ask for web accessibility websites examples, what they really want is the set of habits that well-built sites share. Public sector sites that must publish an accessibility statement are a good place to look. They tend to have:

  • A skip link as the first focusable item, visible when focused.
  • Landmarks: header, nav, main and footer.
  • One h1 and a sensible heading outline.
  • A strong, visible focus style on every control.
  • Body copy that clears the 4.5:1 ratio, and layouts that reflow on a phone.
  • Forms with visible labels and error summaries.
  • A published statement about accessibility, plus a way to report barriers.

A skip link that becomes visible on focus:

<a class="skip" href="#main">Skip to main content</a>
<main id="main">...</main>

For the design side see accessible web design.

How to use these patterns safely

Patterns are a starting point, not proof. Copying code is safe only when you also check it in context.

  1. Check whether a native HTML element already does the job. If it does, use it.
  2. If not, follow the matching pattern in the ARIA Authoring Practices Guide.
  3. Test with the keyboard: Tab, Shift+Tab, Enter, Space, arrow keys and Escape.
  4. Run a screen reader over it and check what it announces: name, role, state.
  5. Zoom to 400 percent and check nothing is lost.
  6. Record the result per criterion, then retest after every change.

Adding ARIA roles without the keyboard behaviour they promise makes things worse. A div with role="button" that ignores Enter is a broken button that now claims to work.

A structured plan is in accessibility testing, and outside help is described in accessibility audit and accessibility services.

Questions people ask

What is an example of web accessibility?

A simple one is alt text on an image, so a blind user hears what the picture shows. Others are captions on video, form labels, enough color contrast and menus that work with a keyboard.

Where can I find WCAG patterns for custom widgets?

W3C publishes the ARIA Authoring Practices Guide, with patterns with keyboard rules for comboboxes, dialogs, tabs, menus and more. Use them as a starting point and test the result, because examples can still fail in a real page.

Is a custom dropdown ever better than a select element?

Only when you need something a select cannot do, such as typing to filter a long list. Then build a combobox following the W3C pattern. For a short list, the native select is more accessible and much less work.

How should a tooltip behave to meet WCAG?

It should appear on focus as well as hover, be dismissible with Escape without moving focus, stay open while the pointer is over it, and not vanish on a timer. Its text should be tied to the trigger with aria-describedby.

What makes a modal dialog accessible?

On opening, focus jumps inside the dialog and stays there until it closes, then returns to the trigger when it closes. The dialog has an accessible name, usually from its heading, and closes with Escape.

Are there examples of fully accessible websites?

Many public sector sites publish accessibility statements and are good to study, but no large site is perfect forever. Look at the patterns they share, such as skip links, landmarks, visible focus and clear forms, rather than copying a whole site.