Semantic HTML and Accessibility

Table of Contents

  1. What "Semantic" Means
  2. The Page Landmarks
  3. Sections, Articles, and Asides
  4. div and span: The Generic Elements
  5. Why Accessibility Matters
  6. Using the Keyboard
  7. Accessibility Checklist
  8. Restructure Your Page
  9. Try It Yourself

1. What "Semantic" Means

An element is semantic when its name tells you what it is, not how it looks. <nav> means "navigation". <div> means nothing.

You could build an entire page from <div> elements and style it to look identical to one built with proper elements. Visually, you couldn't tell them apart. But for everyone and everything that doesn't look at the page, they're completely different:

  • Screen readers announce "navigation" or "main content" and let a user jump directly to them. In a sea of <div>s there's nothing to jump to.
  • Search engines weigh content in <main> and <article> above repeated site chrome.
  • Browsers give semantic elements free behavior: <button> is focusable and works with Enter and Space, <details> expands on click.
  • You can read your own code six months later.

The rule: choose the element for its meaning first, and style it afterwards.

2. The Page Landmarks

A handful of elements describe the major regions of a page. Assistive technology treats them as landmarks — signposts to jump between.

┌──────────────────────────────┐
│ <header>   logo, title       │
│ <nav>      main links        │
├──────────────────────────────┤
│ <main>                       │
│    <section> …               │
│    <section> …               │
├──────────────────────────────┤
│ <footer>   contact, © notice │
└──────────────────────────────┘
ElementUse it for
<header>Introductory content for the page (or a section): site name, logo, headline
<nav>A block of major navigation links
<main>The unique, central content. Exactly one per page
<footer>Closing info for the page (or a section): copyright, contact links

Here's your profile page with landmarks added:

<body>
  <header>
    <h1>Dara Sok</h1>
    <p>Junior web developer, Phnom Penh</p>
    <nav aria-label="Main">
      <ul>
        <li><a href="index.html">Home</a></li>
        <li><a href="about.html">About</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <!-- page content -->
  </main>

  <footer>
    <p>© 2026 Dara Sok</p>
  </footer>
</body>
</html>

The navigation is a list of links inside <nav>, as mentioned in the last chapter. aria-label="Main" gives the landmark a name, which becomes important when a page has more than one <nav> (a main menu and a footer menu, for example).

3. Sections, Articles, and Asides

Inside <main>, three elements group content:

ElementUse it forTest
<section>A themed group of content, with a heading"Could this have its own heading in an outline?"
<article>A self-contained piece that makes sense on its own"Would it still make sense in an RSS feed or when shared by itself?"
<aside>Related but tangential content: a sidebar, a note"Can it be removed without hurting the main flow?"
<main>
  <section id="about">
    <h2>About me</h2>
    <p>…</p>
  </section>

  <section id="projects">
    <h2>Projects</h2>
    <article>
      <h3>Recipe finder</h3>
      <p>A small site for searching Cambodian recipes.</p>
    </article>
    <article>
      <h3>Study timer</h3>
      <p>A Pomodoro timer in plain JavaScript.</p>
    </article>
  </section>
</main>

Each project is an <article> because it stands alone. Each themed group is a <section>, led by a heading. A <section> without a heading is usually a sign you meant <div>.

Two more worth knowing: <figure> with <figcaption> wraps an image and its caption, and <details> with <summary> makes a native click-to-expand box with no JavaScript.

4. div and span: The Generic Elements

Sometimes there's no element that matches, and you only need a hook for styling or grouping. For that there are two meaningless ones:

  • <div> is a generic block container.
  • <span> is a generic inline container.
<div class="card">
  <h3>Study timer</h3>
  <p>Built with <span class="tech">JavaScript</span>.</p>
</div>

They're not bad — layout often needs them. The mistake is using them when a meaningful element exists. Before writing <div>, ask: is this a header, a navigation, a list, a button, a section? If so, use that. Use <div> as a last resort.

5. Why Accessibility Matters

Accessibility (often shortened to a11y) means building so that everyone can use your page, including people who:

  • are blind or have low vision and use a screen reader or magnifier;
  • can't use a mouse and rely on a keyboard or switch device;
  • are deaf or hard of hearing and need captions;
  • are colorblind or have low contrast sensitivity;
  • have a temporary limit — a broken arm, bright sunlight on a phone screen, a slow connection.

That is a lot of people, and you will almost certainly be one of them at some point. It also helps search engines and, in many countries, it's a legal requirement for public sites. The good news: most of it is free if you use semantic HTML correctly. This series builds in accessibility as you go instead of treating it as an extra.

6. Using the Keyboard

Try this on your own page: put your mouse aside and press Tab.

Focus moves from one interactive element (links, buttons, form fields) to the next, showing an outline around the current one. Enter activates a link, and Space or Enter activates a button. Shift+Tab goes backward.

What you should notice:

  • You can reach every link in a sensible order, matching the order in your HTML.
  • You always see where focus is. Never remove the focus outline with outline: none unless you replace it with something just as visible.
  • A <div> with a click handler is not reachable. A real <a> or <button> is, automatically. That's the free behavior semantic elements give you.

A skip link helps keyboard users avoid tabbing through the whole menu on every page. It's the first element in <body>:

<a href="#main">Skip to main content</a>
…
<main id="main">

It's often hidden until focused; chapter 7 shows how to style it.

7. Accessibility Checklist

Keep this list handy for every page you build:

CheckWhy
<html lang="…"> is setRight language and pronunciation
One <h1>, headings in orderNavigable outline
Landmarks: header, nav, main, footerJump between regions
Every <img> has appropriate altContent for people who can't see it
Link text makes sense aloneBrowsing a list of links
Everything works with Tab and EnterKeyboard users
Visible focus outlineSeeing where you are
Enough color contrastChapter 8 covers the numbers
Form fields have labelsChapter 5
Don't convey meaning by color aloneColorblind users

8. Restructure Your Page

Apply this to your project. Open index.html and:

  1. Wrap the title and menu in <header>, with a <nav> containing a <ul> of links.
  2. Wrap the content in <main>, with one <section> per topic (About, Skills, Projects), each starting with an <h2>.
  3. Turn each project into an <article> with an <h3>.
  4. Add a <footer> with the copyright and an email link.
  5. Add a skip link as the first element in <body>.
  6. Give the contact section id="contact" so the nav link works.

Do the same for about.html, with the same header and footer.

9. Try It Yourself

  1. Tab through the page. Use only the keyboard. Does the order make sense? Is the focus always visible?
  2. Run Lighthouse. In Chrome DevTools open the Lighthouse panel, tick Accessibility, and run it. Read any warning it gives you.
  3. Listen to the page. Turn on a screen reader — VoiceOver on macOS (Cmd+F5), Narrator on Windows (Ctrl+Win+Enter), or NVDA (free). Navigate by headings and landmarks. Is your page understandable without seeing it?
  4. Compare. Open a news site and inspect it. How many <div> versus semantic elements does it use? Is there a <main>?
  5. Validate and commit. Run the W3C validator once more. It checks that you used <main> once and nested things correctly.

Next, we'll add the interactive parts of HTML: forms for collecting input, and tables for showing data.

Buy Me a Coffee

Found this tutorial helpful? Consider buying me a coffee to support more free content!