// guide

Semantic HTML: Choosing the Right Elements

Semantic HTML is the single most impactful thing you can do for accessibility. The right elements give you keyboard support, screen reader announcements, and search engine understanding with zero extra code. This guide covers the elements that matter most and when to use each one.

beginner html

// 01 · why semantics matter

Why Semantics Matter

Semantic HTML means using elements for their intended purpose: <button> for actions, <nav> for navigation, <h2> for section headings. When you use the right element, the browser does the hard work for you.

Screen readers use semantic HTML to navigate. Headings become a table of contents. Landmark elements (<nav>, <main>, <aside>) become jump points. Lists announce their item count. Without semantics, assistive technology users get a flat wall of text with no structure.

Built-in keyboard interaction comes free. A <button> is focusable, responds to Enter and Space, and announces its role. A <div onclick> does none of that unless you manually add tabindex, key event listeners, and ARIA roles. Native elements also handle focus management and state announcements (checked, expanded, selected) without any JavaScript.

Search engines benefit too. Crawlers use headings, landmarks, and document structure to understand page content. Semantic HTML improves SEO alongside accessibility.

Maintainability improves. Semantic markup is self-documenting. A developer reading <nav aria-label="Main"> immediately understands the purpose. A developer reading <div class="nav-wrapper"> has to check the CSS and JavaScript to understand what it does.

The golden rule Semantic HTML is accessibility's foundation — get this right and ARIA becomes optional for most components. Reach for ARIA only when no native HTML element provides the semantics you need.

// 02 · landmark elements

Landmark Elements

Landmarks are structural elements that divide a page into meaningful regions. Screen readers let users jump directly between landmarks, skipping over content they don't need. Think of them as a page-level navigation system that assistive technology provides for free.

Element Implicit ARIA Role When to Use
<header> banner The site-wide header containing logo, navigation, and global actions. One per page (as a direct child of <body>).
<nav> navigation A group of navigation links. Use for primary nav, footer nav, breadcrumbs, and table of contents.
<main> main The primary content of the page. Exactly one per page. Skip links typically target this element.
<aside> complementary Content tangentially related to the main content, such as sidebars, related links, or pull quotes.
<footer> contentinfo The site-wide footer containing copyright, legal links, and secondary navigation. One per page (as a direct child of <body>).
<section> region (when labeled) A thematic grouping of content. Only becomes a landmark when given an accessible name via aria-labelledby or aria-label.
<article> article A self-contained piece of content that could stand alone: a blog post, a comment, a product card, or a forum thread.
Multiple <nav> elements need labels When a page has more than one <nav>, screen readers list them all as "navigation." Users can't tell them apart unless you label each one with aria-label. This site uses <nav aria-label="Main navigation"> in the header and <nav aria-label="Breadcrumb"> for the breadcrumb trail — screen reader users hear the difference immediately.

// 03 · heading hierarchy

Heading Hierarchy

Headings (<h1> through <h6>) create a document outline that screen readers expose as a navigable table of contents. Users can list all headings on a page, jump to any heading, or skip between headings at the same level. This makes headings one of the primary ways assistive technology users navigate.

The rules

  • One <h1> per page — this is the page title. It tells users and search engines what the page is about.
  • Don't skip levels — go from <h2> to <h3>, never from <h2> to <h4>. Skipping levels breaks the outline and confuses screen reader users who rely on heading structure to understand content relationships.
  • Headings are not for styling — if you need big bold text, use CSS. Using an <h3> because it looks the right size creates a misleading document structure.

How screen readers use headings

Most screen readers let users press a single key to jump to the next heading (typically H in NVDA and JAWS). Users can also press 1 through 6 to jump to headings at a specific level. On a well-structured page, a user can press H a few times to find the section they want, then start reading. On a poorly structured page, they have to listen to everything linearly.

Common anti-patterns
  • Using <div class="heading"> instead of <h2> — a styled <div> is invisible to screen readers. Users navigating by heading will skip right past it.
  • Skipping <h2> to use <h3> for visual size — this tells assistive technology that the <h3> is a subsection of a non-existent <h2>. Use CSS to style headings at any size you need.
  • Using headings purely for bold text — headings create structural landmarks. If you just need bold text, use <strong> or CSS font-weight.

// 04 · interactive elements: native vs custom

Interactive Elements: Native vs Custom

Native HTML interactive elements come with built-in keyboard support, focus management, ARIA roles, and state announcements. Custom implementations using <div> and <span> require you to recreate all of that manually — and the results are almost always worse.

Need Use This Not This What You Get for Free
Click action <button> <div onclick> Focus, Enter/Space activation, role="button", disabled state
Navigate to a URL <a href> <span onclick> Focus, Enter activation, role="link", right-click context menu, middle-click to open in new tab
Expand/collapse <details>/<summary> Custom div toggle Focus, Enter/Space, expanded/collapsed state announcement, no JavaScript required
Selection from a list <select> Custom dropdown Focus, arrow key navigation, type-ahead search, role="listbox", mobile-optimized picker
Toggle on/off <input type="checkbox"> <div> with ARIA Focus, Space to toggle, checked/unchecked state, works with <label>

When a native element isn't enough — for example, a tabbed interface or a modal dialog — follow the established patterns and lean on ARIA to fill the gaps. See these patterns for accessible implementations:

  • Accordion — uses <details>/<summary> for native expand/collapse
  • Modal Dialog — uses the <dialog> element for native modal behavior
  • Accessible Forms — demonstrates native form controls with proper labeling

// 05 · lists and structure

Lists and Structure

Lists are more than a visual convention. Screen readers announce list structure — "list, 5 items" — giving users context about how much content is in a group and how it's organized. Without list markup, a series of items is just disconnected text.

  • <ul> for unordered lists — navigation menus, feature lists, tag groups. Order doesn't matter. This site's own nav menus use <ul> inside <nav>.
  • <ol> for ordered lists — step-by-step instructions, rankings, table of contents. Order is meaningful. The breadcrumb and table of contents on this page both use <ol>.
  • <dl> for description lists (key-value pairs) — glossaries, metadata, FAQs. Each <dt> is a term, each <dd> is its description.
Lists give context When a screen reader encounters <ul> with five <li> children, it announces "list, 5 items" and users know exactly how much content to expect. With plain <div> elements, they get no count and no indication that the items are related.

// 06 · tables

Tables

HTML tables are for tabular data — information organized into rows and columns where the relationships between cells matter. Screen readers use table markup to let users navigate by row and column, announcing the relevant headers as they move. Without proper table structure, data becomes a meaningless stream of text.

Required table markup

  • <caption> (or aria-label) — gives the table an accessible name so users know what data it contains before reading it.
  • <thead> with <th scope="col"> — marks column headers so screen readers can announce them as users navigate cells in that column.
  • <th scope="row"> — marks row headers so screen readers announce them as users navigate across a row.

See the Data Table pattern for a full implementation with sorting, responsive behavior, and screen reader testing results.

Anti-pattern: faking tables with CSS grid or flexbox Using CSS grid or flexbox to create a visual table layout destroys all table semantics. Screen readers cannot announce column or row headers, users cannot navigate cell by cell, and the data relationships are lost entirely. If your data has rows and columns, use <table>. Always. Visual styling can be applied to real table elements with CSS.

// 07 · form markup

Form Markup

Forms are where accessibility most visibly breaks down. Missing labels, unlabeled groups, and wrong input types create barriers for screen reader users, keyboard users, and mobile users alike. The right HTML elements solve most of these problems.

  • <label> with for attribute — every form control needs a label, and the for attribute must match the input's id. This lets screen readers announce the label when the input is focused, and lets mouse users click the label to focus the input.
  • <fieldset>/<legend> — groups related inputs (radio buttons, checkboxes, address fields) and announces the group label before each input. Without this, screen readers announce "Yes" and "No" with no indication of what question they answer.
  • <input type> — using the correct type (email, tel, url, number, date) triggers the appropriate keyboard on mobile devices and enables built-in validation. An <input type="email"> shows the @ key on iOS; a generic <input type="text"> does not.
  • <output> — represents the result of a calculation or user action. Screen readers announce it as a live region, so users hear updated results without manually navigating to them.

For a complete treatment of accessible form patterns — including validation, error messages, and multi-step forms — see the Accessible Forms pattern.

// 08 · next steps

Next Steps

Semantic HTML is the foundation every other accessibility technique builds on — get the elements right and most of WCAG follows for free. To verify your markup choices in a real codebase, work through the Developer Accessibility Checklist, which maps each check to a WCAG success criterion. When native elements genuinely fall short, the ARIA guide covers when — and when not — to reach for ARIA.