HTML Accessibility
Why accessibility matters
Web accessibility (often abbreviated a11y) means making websites usable by everyone, including people with visual, motor, hearing, or cognitive disabilities. Over 1 billion people worldwide live with some form of disability.
But accessibility isn't just about disabilities. It helps everyone: someone using a slow connection, a person browsing on a phone in bright sunlight, or a power user who navigates entirely by keyboard.
Semantic HTML is the foundation
The single most impactful thing you can do for accessibility is use semantic HTML. Screen readers and assistive technologies rely on the meaning behind elements.
HTML
<!-- Bad: a div pretending to be a button -->
<div onclick="doSomething()">Click me</div>
<!-- Good: an actual button -->
<button onclick="doSomething()">Click me</button>The real
<button> is focusable, responds to Enter/Space keys, and is announced as "button" by screen readers. The <div> does none of that without significant extra work.Headings create structure
Screen reader users often navigate by jumping between headings. Use them in order — don't skip levels:
HTML
<!-- Good -->
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
<!-- Bad — skipped from h1 to h3 -->
<h1>Page Title</h1>
<h3>Section</h3>Only use one
<h1> per page.Labels for form fields
Every form input must have a label. Without one, screen readers can't tell the user what to type:
HTML
<!-- Good: label linked to input -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" />
<!-- Bad: no label -->
<input type="email" placeholder="Email" />Placeholders are not labels — they disappear when you start typing.
ARIA attributes
ARIA (Accessible Rich Internet Applications) adds extra context when HTML alone isn't enough:
HTML
<!-- Tell screen readers this div is a navigation -->
<div role="navigation" aria-label="Main menu">
<a href="/">Home</a>
<a href="/about">About</a>
</div>But the first rule of ARIA is: don't use ARIA if native HTML does the job. This is better:
HTML
<nav aria-label="Main menu">
<a href="/">Home</a>
<a href="/about">About</a>
</nav>Common ARIA attributes
| Attribute | Purpose |
|---|---|
aria-label | Provides an accessible name |
aria-labelledby | Points to another element that labels this one |
aria-hidden="true" | Hides decorative elements from screen readers |
aria-live="polite" | Announces dynamic content changes |
aria-expanded | Indicates if a collapsible section is open |
role | Defines what an element is (button, alert, dialog, etc.) |
Keyboard navigation
Many users navigate with the keyboard instead of a mouse. Ensure:
- All interactive elements are focusable — links, buttons, and inputs are by default. Custom widgets need
tabindex="0". - Focus order makes sense — don't rearrange with CSS in ways that break tab order.
- Focus is visible — never remove the focus outline without providing an alternative.
CSS
/* Bad — removes focus indicator */
*:focus { outline: none; }
/* Good — custom focus style */
*:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}Color and contrast
Text must have sufficient contrast against its background. The WCAG standard requires:
- 4.5:1 ratio for normal text
- 3:1 ratio for large text (18px+ or 14px+ bold)
HTML
<!-- Bad: only color indicates error -->
<input style="border-color: red" />
<!-- Good: color + text + icon -->
<input style="border-color: red" aria-invalid="true" />
<span role="alert">Please enter a valid email.</span>Alt text for images
We covered this in the images lesson, but it's worth repeating:
- Descriptive for informational images:
alt="Bar chart showing sales increased 20% in Q1" - Empty for decorative images:
alt="" - Never use
alt="image"oralt="photo"
Skip links
For keyboard users, add a hidden link that lets them skip past navigation:
HTML
<a href="#main-content" class="skip-link">Skip to main content</a>
<nav><!-- long navigation --></nav>
<main id="main-content">
<!-- page content -->
</main>CSS
.skip-link {
position: absolute;
top: -100%;
left: 0;
}
.skip-link:focus {
top: 0;
z-index: 1000;
background: #fff;
padding: 8px 16px;
}Key takeaway
Accessibility isn't an afterthought — it's a quality standard. Use semantic HTML, label all form fields, ensure keyboard navigation works, maintain color contrast, and add ARIA only when HTML falls short. These practices also improve SEO and general usability.