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>&copy; 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>

❌ Incorrect Hierarchy

<h1>Page Title</h1>
<h4>Skipped levels</h4>
<h2>Out of order</h2>

✅ Correct Hierarchy

<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>

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