Forms & SemanticsBeginner8 min08 / 8

Semantic HTML & Accessibility

Learn how to use meaningful HTML elements that help browsers, search engines, and screen readers understand your page — and why that matters for every user.

Imagine you receive a parcel in the post. The box is completely unlabelled — no indication of what is fragile, which side is up, or who it is for. You could figure it out by opening everything, but it is slow and error-prone. Now imagine the same parcel with clear labels: "FRAGILE", "THIS SIDE UP", "For: Reception". Suddenly anyone who touches that box knows exactly what to do.

HTML elements work the same way. You can build an entire page out of <div> and <span> tags — and it will look fine — but nobody useful gets any labels: not the browser, not a search engine, and not a screen reader used by someone who cannot see the screen. Semantic HTML is the practice of choosing elements whose names describe the content inside them. It is one of the highest-value, lowest-effort improvements you can make as a web developer.

#Semantic vs Non-Semantic Elements

A semantic element carries meaning in its name. <nav> means "this is a navigation menu". <article> means "this is a self-contained piece of content". <button> means "the user can press this".

A <div> means absolutely nothing on its own — it is a generic container with no implied role. Using only <div> tags to build a page is affectionately called div soup. Here is the same page skeleton written two ways:

Every element is a generic box. A screen reader sees no landmarks here.
<!-- DIV SOUP: generic, meaningless to machines -->
<div class="header">
  <div class="nav">...</div>
</div>
<div class="main">
  <div class="article">...</div>
  <div class="sidebar">...</div>
</div>
<div class="footer">...</div>
Each element announces its own purpose. Screen readers can jump straight to <main>.
<!-- SEMANTIC HTML: self-documenting and accessible -->
<header>
  <nav>...</nav>
</header>
<main>
  <article>...</article>
  <aside>...</aside>
</main>
<footer>...</footer>
Think of it like

A city with no street signs

Imagine a city where every road, alley, park, and car park looks identical — same grey concrete, no signs. You can still get around by memorising the layout, but newcomers are lost, emergency services struggle, and GPS is useless.

Semantic HTML is the city's street signs. <header>, <nav>, <main>, and <footer> are landmarks that let everyone — sighted users, assistive technology, and search engine bots — navigate your page instantly.

#The Core Landmark Elements

Here is a bird's-eye view of the seven workhorse semantic elements:

| Element | Purpose | |---|---| | <header> | Introductory content for the page or a section (logo, site title, top nav) | | <nav> | A set of navigation links | | <main> | The primary, unique content of the page — only one per page | | <section> | A thematic grouping that belongs to a larger whole | | <article> | Self-contained content that could stand alone (blog post, news story) | | <aside> | Content tangentially related to the main content (sidebars, pull quotes) | | <footer> | Closing content for the page or a section (copyright, contact links) |

`<article>` vs `<section>` in one sentence: if the content could be copy-pasted to another site and still make sense, use <article>. If it only makes sense as part of the current page, use <section>.

A complete, realistic page using semantic landmarks from top to bottom.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>The Daily Brew — Coffee Blog</title>
</head>
<body>
  <header>
    <h1>The Daily Brew</h1>
    <nav>
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/recipes">Recipes</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <article>
      <h2>Why Cold Brew Takes 12 Hours</h2>
      <p>Unlike hot coffee, cold brew relies on time...</p>
    </article>
    <aside>
      <h2>Related Posts</h2>
      <ul><li><a href="/espresso">Espresso Basics</a></li></ul>
    </aside>
  </main>

  <footer>
    <p>&copy; 2026 The Daily Brew</p>
  </footer>
</body>
</html>

#Accessibility & Alt Text

Roughly 1 in 6 people worldwide lives with some form of disability. Many browse the web using screen readers — software that reads page content aloud. Screen readers treat semantic elements as landmarks that users can jump between with a single keypress.

A screen reader user can skip directly to <main>, bypassing the header and navigation they have already heard. Without semantic markup, there are no landmarks — they must listen to every link and heading from the very top, on every page load.

Images are invisible to screen readers unless you describe them with an alt attribute. Write alt text that describes what the image shows — not its file name, not the word "image".

The alt test: if you read it aloud to someone with their eyes closed, would they understand the image?
<!-- Too vague — tells the user nothing -->
<img src="coffee.jpg" alt="image">

<!-- Just right — paints a picture -->
<img src="coffee.jpg" alt="A glass of iced cold brew coffee on a wooden table">

<!-- Decorative only — leave alt empty so screen readers skip it -->
<img src="divider.png" alt="">
Common mistake

Do not replace every div with a semantic element

Semantic elements are for content regions — they do not replace every layout <div>. If you need a flex container purely for visual alignment with no semantic meaning, a <div> is the correct choice. The rule of thumb is: content regions get semantic elements; layout helpers use divs.

Also remember: <main> should appear only once per page, and heading levels should always go in order (<h1><h2><h3>) — never skip levels just to change size. Use CSS for sizing.

Quick check

A developer is marking up a self-contained news story that could be syndicated to another website unchanged. Which element is the best choice?

Key takeaways

  • Semantic elements like <header>, <nav>, <main>, <article>, <aside>, and <footer> label what content *is* — not just where it sits on screen.
  • Screen readers use these landmarks so users can skip directly to the content they need; div soup forces them to listen to everything from the top.
  • Every meaningful image needs an alt attribute that describes what it shows; purely decorative images get an empty alt="".
  • Use <article> for self-contained content and <section> for thematic chunks of a larger page — and keep <main> to one per page.
  • Semantic HTML benefits users, assistive technology, and search engines simultaneously, making it one of the easiest high-impact improvements in web development.
Practice challenges
Test yourself · earn XP
0/4
Predict the output#1

A screen reader user loads this page and presses the key to jump between landmarks. What can they do that they could NOT do with a page built entirely of <div> tags?

predict-output
<header>
  <nav>...</nav>
</header>
<main>
  <article>Why Cold Brew Takes 12 Hours...</article>
</main>
<footer>&copy; 2026 The Daily Brew</footer>
Fix the bug#2

This code has a bug — what's wrong?

fix-bug
<img src="cold-brew.jpg" alt="image">
Fill in the blank#3

Complete the tag so this self-contained blog post — one that could be syndicated to another site unchanged — uses the correct semantic element.

<main>
  <>
    <h2>Why Cold Brew Takes 12 Hours</h2>
    <p>Unlike hot coffee, cold brew relies on time...</p>
  </>
</main>
Reorder the lines#4

Arrange these lines into a valid semantic page skeleton, from the top of the body to the bottom.

1
<main>...</main>
2
  <nav>...</nav>
3
<header>
4
<footer>&copy; 2026 The Daily Brew</footer>
5
</header>
Your turn
Practice exercise

The page below is built entirely out of divs (div soup). Rewrite it using proper semantic HTML. Make sure to: (1) replace structural divs with <header>, <nav>, <main>, <article>, <aside>, and <footer>; (2) add a meaningful alt attribute to the image; (3) add lang="en" to the <html> tag.

Try it live — edit the code and hit Run to see it rendered:

solution.html · editable