Guide · 9 min read · Updated

Semantic HTML explained with before-and-after examples

Illustration of a messy pile of grey boxes turned into a clearly structured web page

Give a div a big bold font and it looks exactly like a real heading. To a screen reader, though, one is a heading and the other is a line of text, and a blind visitor jumping from heading to heading will never land on it. Semantic HTML is the habit of choosing elements for what the content is: a heading goes in <h2>, navigation in <nav>, and anything you click to make something happen is a <button>. Browsers, assistive technology and search engines all build their picture of the page from those tags.

We cover what "meaning" looks like in the browser, then the landmark elements, then the <article> versus <section> question that confuses nearly everyone. After that we take a page made of nested <div> elements and rewrite it properly. A checklist closes the guide. Open the playground in another tab if you want to follow along.

What the browser does with meaning

The HTML Living Standard (opens in a new tab), the specification browsers implement, gives every element a meaning. <p> is a paragraph. <ul> is a list whose order does not matter. <time> is a date or a time. Two elements mean almost nothing: <div> is a generic block container and <span> a generic inline one.

From your HTML the browser builds an accessibility tree, a stripped-down copy of the page that assistive technology reads. Each element in it has a role (button, link, heading, list, navigation), a name (its visible text or label) and sometimes a state (checked, expanded, disabled). A real <button> arrives with the role "button", keyboard support and focus already built in. A <div> dressed up as a button arrives with none of that.

With the right CSS these two lines look identical. Only the first one is a heading to a screen reader:

<h2>Opening hours</h2>
<div class="big-bold">Opening hours</div>

So choose the element that describes the content first, and make it look the way you want with CSS afterwards. A generic container is still sometimes the right answer, and the lesson on div and span shows when.

Landmarks divide the page into regions

Landmarks are the large regions of a page. A screen reader can list them and jump straight to one, which is roughly what a sighted visitor does when glancing at a layout. The W3C landmark regions guidance (opens in a new tab) describes each role in detail. In HTML you get them from these elements:

ElementLandmark roleUse it for
<header>bannerSite header with logo and title (only when it is not inside article, aside, main, nav or section)
<nav>navigationMajor blocks of navigation links
<main>mainThe main content, unique to this page
<aside>complementaryRelated content that stands apart, such as a sidebar
<footer>contentinfoSite footer with copyright and contact links (same scoping rule as header)
<search>searchA search form or filter controls
<section> or <form>region / formOnly when given an accessible name, for example with aria-labelledby

Put together, a typical page looks like this:

<body>
  <header>
    <a href="/">Bake School</a>
    <nav aria-label="Main">
      <ul>
        <li><a href="/recipes/">Recipes</a></li>
        <li><a href="/about/">About</a></li>
      </ul>
    </nav>
  </header>
  <main>
    <h1>Sourdough for beginners</h1>
    ...
  </main>
  <footer>
    <p>&copy; 2026 Bake School</p>
  </footer>
</body>

A page gets one visible <main>, and it never goes inside <article>, <aside>, <header>, <footer> or <nav>. When there is more than one <nav>, give each a short aria-label such as "Main" or "Breadcrumb", or a screen reader user hears "navigation" twice and has to guess. Practise in Header, Nav, Main, Footer and check the details in the nav reference.

Article, section or div: three questions to decide

No three elements cause more arguments in code review. Ask these questions in order and stop at the first yes:

  1. Would this still make sense on its own, pasted into a feed or onto another site? Then it is an <article>. Blog posts, news stories, product cards, forum posts and comments all qualify.
  2. Is it a themed part of something larger, with a heading of its own? Then it is a <section>. Chapters, tab panels and the "Ingredients" and "Method" parts of a recipe are sections.
  3. Is it there only for styling or scripting? Then use a <div>, which exists for exactly that.

Nesting works both ways round. A long article can hold sections, and a "Latest posts" section can hold several articles:

<section aria-labelledby="latest">
  <h2 id="latest">Latest posts</h2>
  <article>
    <h3><a href="/blog/rye/">Baking with rye</a></h3>
    <p>Rye flour behaves differently from wheat...</p>
  </article>
  <article>
    <h3><a href="/blog/starter/">Feeding your starter</a></h3>
    <p>A starter needs flour, water and time...</p>
  </article>
</section>

If you write a <section> and cannot think of a heading for it, you probably wanted a <div>. The fourth element in this family, <aside>, holds content that is related but could be deleted without breaking the main flow, such as a glossary box or a list of related links. The lesson Article, Section, Aside has exercises for each.

Heading levels are the only outline that counts

Older tutorials say each <section> can start over with its own <h1>. That idea, the document outline algorithm, was never implemented by a single browser or screen reader, and it was removed from the HTML standard in 2022. The outline of a page is its heading levels and nothing else.

  • Open the main content with one <h1> that names the page.
  • Use <h2> for the main parts, <h3> for parts inside those, and so on down.
  • Do not skip a level on the way down, such as an <h4> directly after an <h2>. Jumping back up is fine.
  • Never pick a level for its font size. Resize it in CSS.

Many screen reader users move around a page by headings alone, so a tidy hierarchy is one of the most useful things you can give them. See Headings and Heading Order.

Rewriting a page of div soup

"Div soup" is a page built almost entirely from <div> and <span> elements, with class names doing the job that tags should do. BadHTML (opens in a new tab), a satirical collection of what not to do, shows how far the habit can go. Here is a typical specimen:

<div class="header">
  <div class="logo">Bake School</div>
  <div class="menu">
    <span onclick="go('/recipes/')">Recipes</span>
  </div>
</div>
<div class="content">
  <div class="title">Sourdough for beginners</div>
  <div class="date">3 March 2026</div>
  <div class="text">You need three things...</div>
  <div class="btn">Save recipe</div>
</div>

A screen reader finds no landmarks and no heading here. The "menu" item cannot be reached with Tab, and the "button" is plain text that happens to be clickable with a mouse. A search engine sees one undivided block. Here is the same content with meaningful elements:

<header>
  <a href="/">Bake School</a>
  <nav aria-label="Main">
    <a href="/recipes/">Recipes</a>
  </nav>
</header>
<main>
  <article>
    <h1>Sourdough for beginners</h1>
    <p><time datetime="2026-03-03">3 March 2026</time></p>
    <p>You need three things...</p>
    <button type="button">Save recipe</button>
  </article>
</main>

The design does not have to change at all; keep your classes and your CSS. What changes is behaviour. The link now works from the keyboard and opens in a new tab with a middle click. The button takes focus and responds to Enter and Space. The date is machine-readable, and the page has a banner, a navigation region, a main region and a heading. Try the rewrite yourself in Fix the Div Soup.

What semantics does for accessibility, SEO and the next developer

Accessibility

Semantic elements hand assistive technology the roles, names and relationships it needs. That is most of WCAG 2.2 success criterion 1.3.1 Info and Relationships (opens in a new tab), which asks that any structure shown visually also exists in the code. Keyboard users get focusable controls without a line of JavaScript. And it is the first rule of ARIA: when an HTML element already does the job, use it, and do not bolt role attributes onto a <div>.

SEO

Some care is needed here, because a lot of nonsense gets written about it. Google gives no ranking bonus for <article> over <div>. Semantic HTML makes your content easier to process. Headings say what each part is about, real <a href> links are the ones Google crawls, <img> with alt text says what a picture shows, and a clear main region is easier to separate from menus and footers. The benefit is indirect, as the HTML for SEO guide explains, and the lesson on viewport and meta description covers the head tags that count most.

Maintenance

The benefit people forget is for whoever edits the file next. <nav> and <footer> say what a block is much faster than <div class="wrap-2">, and your CSS selectors get shorter as well.

Small elements inside your text

Meaning does not stop at page regions. Inside a paragraph, these elements say things that styling cannot:

A ten-point check for any page

Go through these on every page before you call it finished:

  1. The page has one <main>, plus <header>, <nav> and <footer> where they apply.
  2. If there are several <nav> elements, each has its own aria-label.
  3. There is one <h1>, and heading levels never skip on the way down.
  4. Every <section> has a heading. If it cannot have one, it is a <div>.
  5. Self-contained items such as posts, cards and comments are <article> elements.
  6. Anything that goes to another URL is an <a href>, and anything that performs an action is a <button>.
  7. Lists are lists, tables hold data and quotations use <blockquote>.
  8. Images have meaningful alt text, or alt="" when they are pure decoration.
  9. Every form field has a <label>.
  10. No element was chosen because of how it looks by default.

To see what your page actually exposes, open the accessibility inspector in Chrome or Firefox DevTools and look at the roles and names. Keep the HTML cheat sheet handy for element names.

Frequently asked questions

What is semantic HTML?

Markup in which every element is picked for the meaning of its content: <nav> for navigation, <h2> for a heading, <button> for an action. Browsers, screen readers and search engines read those meanings. Non-semantic elements such as <div> and <span> say nothing about their content and are meant for grouping and styling hooks.

What is the difference between article and section in HTML?

An <article> stands on its own: a blog post, a news story or a comment would make sense anywhere. A <section> is a themed part of something larger, such as a chapter or the "Ingredients" part of a recipe, and it should normally have a heading. A group that exists only for styling is a <div>.

Does semantic HTML improve SEO?

Not as a direct ranking factor. Google does not reward <article> over <div> for its own sake. The help is indirect: headings describe topics, real <a href> links are the links Google can crawl (opens in a new tab), images with alt text can be understood, and the main content is easier to pick out. It also makes the page more accessible, which helps every visitor.

Can a page have more than one header or footer?

Yes. Only the <header> or <footer> that belongs to the whole page becomes a banner or contentinfo landmark. You can use more of them inside an <article> or <section> for that item's title area or byline. The page should still have just one visible <main> element.

Is it wrong to use div in HTML?

No. <div> is the right element when you need a container purely for layout or styling and nothing else describes the content. The problem is using it for things that already have an element, such as headings, navigation, lists or buttons. Reach for semantic elements first and use <div> for whatever is left.

Practise it in the course

Try it in the playground

More guides