HTML Semantic Accessibility
1. Semantic HTML5 Elements (nav, main, article, section)
| Element | Purpose | Accessibility Impact | Use Case |
|---|---|---|---|
| <header> | Introductory content container | Screen readers identify as banner landmark when top-level | Site/page header with logo, navigation |
| <nav> | Navigation links container | Creates navigation landmark for quick access | Main menu, breadcrumbs, table of contents |
| <main> | Primary page content | Defines main landmark, skip to content target | Core article, application interface (one per page) |
| <article> | Self-contained composition | Independent content region for screen readers | Blog post, news story, widget, forum post |
| <section> | Thematic content grouping | Creates region with accessible name (use with heading) | Chapters, tabbed panels, themed content blocks |
| <aside> | Tangentially related content | Complementary landmark for sidebars | Sidebar, pull quotes, related links, ads |
| <footer> | Footer information | Contentinfo landmark when page-level | Copyright, contact, sitemap links |
| <figure> / <figcaption> | Self-contained illustration | Associates caption with image for context | Images, diagrams, code snippets with captions |
Example: Semantic page structure with landmarks
<header>
<nav aria-label="Main navigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main id="main-content">
<article>
<h1>Article Title</h1>
<p>Content...</p>
</article>
<aside aria-label="Related articles">
<h2>Related Content</h2>
</aside>
</main>
<footer>
<p>© 2025 Company</p>
</footer>
Note: Use one <main> per page and ensure semantic elements
are not nested incorrectly (e.g., no <main> inside <aside>).
2. ARIA Landmark Roles (role="navigation", "main", "banner")
| ARIA Role | HTML5 Equivalent | Purpose | Labeling Requirement |
|---|---|---|---|
| role="banner" | <header> (page-level) | Site-wide header with branding | Optional: aria-label if multiple banners |
| role="navigation" | <nav> | Collection of navigation links | Required: aria-label when multiple navs |
| role="main" | <main> | Primary content of page | None (only one per page) |
| role="complementary" | <aside> | Supporting content | Recommended: aria-label for clarity |
| role="contentinfo" | <footer> (page-level) | Page footer information | None (implied semantics) |
| role="region" | <section> with name | Generic landmark for important content | Required: aria-labelledby or aria-label |
| role="search" | None (use role) | Search functionality container | Optional: aria-label "Site search" |
| role="form" | <form> with name | Form landmark (when named) | Required: aria-label or aria-labelledby |
Example: Multiple navigation landmarks with labels
<nav aria-label="Primary navigation">
<!-- Main menu -->
</nav>
<nav aria-label="Breadcrumb" aria-describedby="breadcrumb-desc">
<span id="breadcrumb-desc" hidden>Current page location</span>
<ol>
<li><a href="/">Home</a></li>
<li>Current Page</li>
</ol>
</nav>
<div role="search">
<form role="search" aria-label="Site search">
<input type="search" aria-label="Search query">
<button type="submit">Search</button>
</form>
</div>
Warning: Don't overuse landmarks - too many can be overwhelming. Prefer
HTML5 semantic elements over explicit ARIA roles when available.
3. Heading Hierarchy (h1-h6) Best Practices
| Rule | Requirement | Accessibility Impact | Example |
|---|---|---|---|
| Start with H1 | One H1 per page describing main topic | Screen reader users navigate by headings; H1 identifies page purpose | <h1>Product Name</h1> |
| Sequential Order | Don't skip levels (H1→H2→H3, not H1→H3) | Preserves document outline, prevents confusion | H1 > H2 > H3 > H2 > H3 |
| Visual vs Semantic | Use CSS for sizing, not wrong heading level | Maintain logical structure independent of appearance | <h2 class="small"> not <h4> |
| Section Headings | Every <section> should have a heading | Provides accessible name for region | <section><h2>...</h2></section> |
| Landmark Headings | Landmarks benefit from descriptive headings | Helps identify region content quickly | <nav><h2>Main Menu</h2></nav> |
| Hidden Headings | Use visually-hidden class for structure |
Provides screen reader navigation without visual clutter | <h2 class="sr-only">Filters</h2> |
Example: Proper heading hierarchy
<main>
<h1>Dashboard</h1>
<section>
<h2>Recent Activity</h2>
<article>
<h3>Task Completed</h3>
<p>Details...</p>
</article>
</section>
<section>
<h2>Statistics</h2>
<div>
<h3>This Month</h3>
<!-- Stats -->
</div>
</section>
</main>
4. Document Language (lang attribute) and Direction
| Attribute | Scope | Purpose | Example Value |
|---|---|---|---|
| lang | Document/Element | Specifies language for pronunciation and hyphenation | lang="en", lang="es" |
| lang (regional) | Element-level | Region-specific language variant | lang="en-US", lang="pt-BR" |
| dir | Document/Element | Text direction for RTL languages | dir="ltr", dir="rtl" |
| dir="auto" | Element-level | Automatic direction based on content | dir="auto" for user input |
| translate | Element | Indicates if content should be translated | translate="no" for brand names |
Example: Language and direction declarations
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Multilingual Page</title>
</head>
<body>
<h1>Welcome</h1>
<!-- Spanish section -->
<section lang="es">
<h2>Bienvenido</h2>
<p>Contenido en español...</p>
</section>
<!-- Arabic RTL section -->
<section lang="ar" dir="rtl">
<h2>مرحبا</h2>
<p>محتوى باللغة العربية...</p>
</section>
<!-- Brand name not translated -->
<p>Our product <span lang="en" translate="no">AccessibleUI</span></p>
</body>
</html>
| Common Language Codes | Code | Regional Variants |
|---|---|---|
| English | en |
en-US, en-GB, en-CA, en-AU |
| Spanish | es |
es-ES, es-MX, es-AR |
| French | fr |
fr-FR, fr-CA, fr-BE |
| German | de |
de-DE, de-AT, de-CH |
| Arabic (RTL) | ar |
ar-SA, ar-EG, ar-AE |
| Hebrew (RTL) | he |
he-IL |
| Chinese | zh |
zh-CN (Simplified), zh-TW (Traditional) |
| Japanese | ja |
ja-JP |
Note: Always set lang on <html> element. Screen readers
use this to select proper voice and pronunciation rules.
5. Page Titles and Meta Information
| Element/Meta | Purpose | Accessibility Impact | Best Practice |
|---|---|---|---|
| <title> | Browser tab and bookmark text | First thing announced by screen readers; helps identify page | Unique, descriptive, front-load important info |
| viewport meta | Responsive scaling control | Enables pinch-zoom; critical for low vision users | user-scalable=yes, no maximum-scale |
| charset meta | Character encoding | Ensures proper text rendering across languages | <meta charset="UTF-8"> always |
| description meta | Search result snippet | Helps users understand page content before visiting | Concise, accurate, 150-160 characters |
| theme-color meta | Browser UI color | Visual consistency; supports high contrast needs | Match brand, ensure sufficient contrast |
Example: Accessible HTML head structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Descriptive, unique title (50-60 chars ideal) -->
<title>Product Features - AccessibleUI Design System</title>
<!-- Clear page description -->
<meta name="description" content="Explore accessible UI components
with WCAG 2.2 AA compliance, including buttons, forms, and navigation.">
<!-- Theme color for browser UI -->
<meta name="theme-color" content="#007acc">
<!-- Skip to main content link -->
<link rel="stylesheet" href="styles.css">
</head>
| Title Pattern | Context | Example |
|---|---|---|
| Page - Site | General pages | <title>About Us - Company Name</title> |
| Item - Category - Site | Detail pages | <title>Blue Widget - Products - Store</title> |
| Status - Action - Site | Form/app states | <title>Error - Checkout - Store</title> |
| Dynamic Update | SPAs, notifications | <title>(3) Messages - Inbox</title> |
Example: Accessible viewport configuration
<!-- ✅ CORRECT: Allows user zoom -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ❌ WRONG: Disables zoom (WCAG failure) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no">
Warning: Never use
user-scalable=no or maximum-scale=1.0 - this
violates WCAG 2.2 Success Criterion 1.4.4 (Resize Text) and prevents users from
zooming.
Section 1 Key Takeaways
- Use semantic HTML5 elements (header, nav, main, article, aside, footer) for automatic landmark roles
- Ensure proper heading hierarchy (H1→H2→H3) without skipping levels
- Always declare lang attribute on <html> element for screen reader pronunciation
- Create unique, descriptive page titles that identify content and context
- Never disable zoom/scaling in viewport meta tag
- Label multiple landmarks of same type with aria-label for differentiation