HTML Accessibility
Accessibility means making web pages usable for everyone — including people who use screen readers, keyboard navigation, or other assistive tools due to visual, physical, or cognitive differences. Good HTML accessibility also improves SEO and benefits all users, not just those with disabilities.
Who Benefits from Accessibility
Visual Diagram — Types of Users
All Website Visitors
|
├── Sighted users using a mouse or touch
├── Blind users using a screen reader
├── Low-vision users using zoom or high contrast
├── Deaf users needing captions on videos
├── Motor-impaired users using keyboard only
├── Users with cognitive differences
└── Slow-connection users (accessibility helps them too)
Accessible HTML reaches all of these groups at once.
The alt Attribute on Images
Screen readers cannot see images. The alt attribute provides a text description that screen readers read aloud in place of the image.
<!-- Descriptive alt text --> <img src="html-structure-diagram.png" alt="Diagram showing the nested structure of an HTML document with html, head, and body tags"> <!-- Decorative image — empty alt so screen reader skips it --> <img src="decorative-line.png" alt="">
Rules for Good alt Text
Image Type What to Write
-------------- ------------------------------------------
Informational image Describe what the image shows
Linked image Describe the link destination ("Go to homepage")
Chart or graph Summarize the key data point it shows
Decorative image Write alt="" (empty) — screen reader skips it
Logo with text Include the company name in the alt text
Semantic HTML Tags
Semantic tags communicate the meaning of content to assistive technology. A screen reader reads <h1> and announces "Heading level 1". It reads <nav> and announces "Navigation". It reads <div> and says nothing extra — a div has no meaning.
<!-- Not accessible: no structure information --> <div class="header">My Site</div> <div class="nav">Home | About | Contact</div> <!-- Accessible: structure is clear --> <header>My Site</header> <nav> <a href="/">Home</a> <a href="/about">About</a> <a href="/contact">Contact</a> </nav>
Heading Hierarchy
Screen reader users navigate pages by jumping between headings. Use heading levels in the correct order — one <h1> per page, then <h2> for main sections, <h3> for subsections, and so on. Never skip levels.
Visual Diagram — Correct vs Incorrect Heading Structure
Correct structure (like a book outline):
H1: HTML Tutorial
H2: HTML Basics
H3: Tags
H3: Elements
H2: HTML Forms
H3: Input Types
Wrong structure (skips levels — confuses screen readers):
H1: HTML Tutorial
H3: Tags ← skipped H2
H5: Examples ← skipped H4
Labels for Form Fields
Every form input needs a visible label. Screen readers announce the label when the user focuses on the input. Without a label, the user does not know what the field is for.
<!-- Correct: label connected via for + id --> <label for="email">Email Address</label> <input type="email" id="email" name="email"> <!-- Also correct: label wraps the input --> <label> Phone Number <input type="tel" name="phone"> </label> <!-- Wrong: placeholder is not a label replacement --> <input type="email" name="email" placeholder="Email Address">
Placeholder text disappears when the user starts typing. If the placeholder is the only label, the user forgets what the field is for by the time they finish typing.
Keyboard Navigation
Many users navigate web pages using only the keyboard — pressing Tab to move between interactive elements, Enter to activate links and buttons, and arrow keys to move within components.
HTML elements that receive keyboard focus by default:
<a href="..."> → links <button> → buttons <input> → form fields <select> → dropdowns <textarea> → text areas
Non-interactive elements like <div> and <span> do not receive focus. When you make a <div> clickable with JavaScript, add tabindex="0" so keyboard users can reach it too.
<div tabindex="0" role="button" onclick="doSomething()">Click Me</div>
The tabindex Attribute
The tabindex attribute controls whether and in what order an element receives keyboard focus.
tabindex="0" → element joins the natural tab order tabindex="-1" → element can be focused by JavaScript but not by Tab key tabindex="1" → element comes first in tab order (avoid — causes confusion)
Setting positive tabindex values like tabindex="3" overrides the natural order and confuses users. Use tabindex="0" for elements that should be reachable and tabindex="-1" for elements you manage programmatically.
ARIA Roles and Attributes
ARIA (Accessible Rich Internet Applications) attributes add accessibility information to HTML elements when native semantic tags are not enough.
role Attribute
The role attribute tells assistive technology what an element is.
<div role="navigation">...</div> → same meaning as <nav> <div role="main">...</div> → same meaning as <main> <div role="button">...</div> → acts like a button <div role="alert">Error!</div> → screen reader announces immediately
aria-label Attribute
The aria-label attribute provides a text name for an element when no visible text label exists.
<button aria-label="Close dialog">✕</button>
Without aria-label, the screen reader would just say "button" with no further information. With it, the reader says "Close dialog, button."
aria-labelledby Attribute
When a visible heading or text already describes an element, reference that text with aria-labelledby instead of repeating it in aria-label.
<h2 id="contact-heading">Contact Form</h2> <form aria-labelledby="contact-heading"> ... </form>
aria-hidden Attribute
The aria-hidden="true" attribute hides an element from screen readers while keeping it visible on screen. Use it for decorative icons or duplicate text that would confuse screen reader users.
<button> <span aria-hidden="true">🔍</span> Search </button>
Without aria-hidden, the screen reader would say "magnifying glass emoji Search button." With it, the reader says only "Search button."
aria-expanded Attribute
Use aria-expanded on buttons that control collapsible content. Set it to "true" when the content is open and "false" when closed.
<button aria-expanded="false" aria-controls="menu">Menu</button> <ul id="menu" hidden> <li><a href="/">Home</a></li> </ul>
Color Contrast
Text must have sufficient contrast against its background so users with low vision can read it. The WCAG standard requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text.
Visual Diagram — Contrast Examples
Hard to read (low contrast): Light gray text on white background → BAD Yellow text on white background → BAD Easy to read (high contrast): Black text on white background → GOOD White text on dark blue background → GOOD Dark text on light yellow background → GOOD
Free online tools like the WebAIM Contrast Checker let you test any foreground and background color combination and show whether it passes WCAG requirements.
Skip Navigation Link
A skip link is a hidden link at the very top of a page that lets keyboard users jump directly to the main content, bypassing the navigation menu. Without it, keyboard users must press Tab many times through every navigation link on every page they visit.
<a href="#main-content" style="position:absolute; left:-9999px;"> Skip to main content </a> <nav>...</nav> <main id="main-content"> ... </main>
The link is invisible until a keyboard user presses Tab once — then it appears, allowing them to jump past the navigation with a single press of Enter.
Video and Audio Accessibility
Videos need captions for deaf users. Audio content needs transcripts. The <track> element adds captions or subtitles to a <video> element.
<video controls> <source src="lesson.mp4" type="video/mp4"> <track kind="captions" src="captions-en.vtt" srclang="en" label="English" default> </video>
Accessibility Quick Checklist
✓ All images have descriptive alt text (or alt="" if decorative) ✓ Headings follow correct order: H1 → H2 → H3 ✓ Every form input has a <label> ✓ Color contrast passes WCAG 4.5:1 ratio ✓ All interactive elements reachable by keyboard ✓ Videos have captions ✓ Skip navigation link at top of page ✓ Semantic HTML used throughout (header, nav, main, etc.)
Accessibility is not a checklist to complete at the end — it is a way of writing HTML from the start. Accessible pages rank better in search engines, work on more devices, and serve every visitor, regardless of how they experience the web.
