Accessible HTML
About one in six people lives with a disability, and everyone is temporarily impaired sometimes: a broken arm, a bright screen, a noisy train. Accessible HTML is mostly not extra work. It is using the elements the browser already understands.
Semantics carry meaning
Screen readers, voice control and keyboard navigation all rely on the accessibility tree, which the browser builds from your HTML. A <button> arrives in that tree as a button: focusable, announced as “button”, activated by Enter and Space. A <div> with a click handler arrives as nothing.
<!-- Looks like a button, isn't one: no focus, no keyboard, no role -->
<div class="btn" onclick="save()">Save</div>
<!-- Is a button, for free -->
<button type="button" onclick="save()">Save</button>
Use landmarks so people can jump around the page: <header>, <nav>, <main>, <footer>. Use headings <h1> to <h6> in order, because screen reader users often navigate by heading list. Use <a href> for navigation and <button> for actions; mixing them up breaks expectations such as opening a link in a new tab.
Every input needs a label
A placeholder is not a label: it disappears when you type and is often low contrast.
<label for="email">Email</label>
<input id="email" type="email" autocomplete="email" required>
Clicking the label focuses the input, and a screen reader announces “Email, edit text, required”. For groups of radio buttons or checkboxes, wrap them in <fieldset> with a <legend> so the question is read with each option.
Text alternatives
Every meaningful image needs alt text that says what the image communicates, not what it looks like. A chart’s alt text should state its conclusion. Decorative images get an empty alt="" so assistive technology skips them. Icon-only buttons need an accessible name, either visually hidden text or aria-label.
Keyboard access and focus
Everything you can do with a mouse must work with a keyboard. Test by unplugging the mouse: press Tab through the page and check that:
- every interactive element receives focus, in a logical order;
- the focused element is clearly visible (never remove the outline without replacing it);
- nothing traps focus, except a modal dialog while it is open;
- when content changes, focus moves somewhere sensible. After opening a dialog, focus goes into it; after closing it, focus returns to the button that opened it.
Avoid positive tabindex values; they create a focus order nobody can predict.
ARIA: the first rule
ARIA attributes change what the accessibility tree says about an element. The first rule of ARIA is don’t use ARIA if a native element does the job. role="button" on a <div> promises button behaviour, but you must then add focus, Enter and Space handling yourself.
ARIA shines where HTML has no equivalent:
aria-live="polite"announces updates such as “Saved” or search result counts;aria-expandedtells users whether a disclosure is open;aria-describedbylinks an input to its error message.
Colour and contrast
Body text needs a contrast ratio of at least 4.5:1 against its background (3:1 for large text). Never use colour alone to carry meaning: a red border on an invalid field also needs an error message or icon.
Test it
Automated checkers such as axe catch roughly a third of issues: missing labels, low contrast, invalid ARIA. The rest needs people: a keyboard pass, a screen reader pass (VoiceOver on macOS and iOS, NVDA on Windows, TalkBack on Android) and zooming to 200%.