Semantic Elements

Understand what semantic HTML elements are, why they matter more than generic <div> soup, and how to structure a page using header, nav, main, section, article, aside, footer, address, and time.

Every piece of a web page can technically be built out of nothing but <div> tags. Browsers won't complain, and visually nobody would notice the difference. But HTML is not just a layout tool — it is a language for describing the *meaning* of content, and that meaning is read by more than just your eyes. Screen readers, search engine crawlers, browser extensions, and even your own teammates six months from now all rely on HTML elements that describe what a piece of content *is*, not just where it sits on the page. This lesson introduces semantic elements: tags whose names tell everyone, human or machine, exactly what role a section of the page plays.

What "semantic" actually means

A semantic element is one whose tag name clearly describes its meaning to both the browser and the developer. <button> is semantic — it tells you and the browser "this is a clickable control." <div> and <span> are non-semantic — they say nothing about their content; they exist purely as generic containers for styling or scripting hooks.

Before HTML5, developers built page structure entirely from <div id="header">, <div id="nav">, <div id="footer">, and so on. That worked visually, but it left machines guessing. HTML5 introduced a set of structural elements — header, nav, main, section, article, aside, footer — specifically so that page structure could be expressed in the markup itself, not just inferred from id names that a machine can't reliably parse.

Why it matters: four concrete reasons

It's tempting to treat semantic tags as a style preference, but they have real, measurable effects on your site.

• Accessibility: screen readers build a "landmarks" list from elements like <nav>, <main>, and <aside>. A blind user can jump straight to "main content" or "navigation" with a keystroke — but only if you used the real elements instead of <div class="main">. • SEO: search engines weigh content inside <article> and <main> differently from content in <aside> or <footer>, and use <nav> to understand your site's link structure. Semantic markup helps crawlers figure out what actually matters on the page. • Maintainability: six months from now, <footer> is self-documenting; <div class="bottom-wrap-2"> is not. Semantic tags make your codebase readable without needing a class-naming dictionary. • Free browser behavior: some semantic elements come with built-in behavior or styling hooks — for example, browsers expose <nav> regions to accessibility APIs automatically, with zero extra code from you.

The core structural elements

<header> represents introductory content for its nearest sectioning ancestor — often a logo, site title, and top-level navigation, but it can also introduce a single <article>.

<nav> wraps a major block of navigation links — primary site navigation, a table of contents, or pagination. Not every group of links needs <nav>; use it for major navigation blocks, not for a couple of inline links in a paragraph.

<main> wraps the primary, unique content of the page — the content that isn't repeated across other pages (so not the header, footer, or sidebar navigation). There should be exactly one visible <main> per page.

<section> groups a thematically related chunk of content, generally with its own heading. Think of it as a generic, meaningful chapter of a document.

<article> wraps content that could stand alone and be independently distributed — a blog post, a news story, a forum comment, a product card. Ask yourself: "could this be syndicated on its own in an RSS feed?" If yes, it's an <article>.

<aside> holds content tangentially related to the main content — a sidebar, a pull quote, related links, or an ad block.

<footer> represents footer content for its nearest sectioning ancestor — copyright notices, contact links, or site map links, and like <header>, it can belong to an <article> as well as the whole page.

<address> marks up contact information for its nearest article or the page as a whole — physical address, email, or phone number of the content's author. It should not be used for arbitrary postal addresses that aren't contact info.

<time> marks up a specific date or time in a machine-readable way using the datetime attribute, so a date printed as "Sep 14, 2026" can also be understood by software as an exact ISO date.

A typical semantic page skeleton

header and footer can appear both at the page level and inside a single article. There should be only one <main> visible in the page at a time. section and article can be nested inside each other when it makes semantic sense.

<body>
  <header>
    <h1>Site Title</h1>
    <nav>...</nav>
  </header>

  <main>
    <article>...</article>
    <section>...</section>
  </main>

  <aside>...</aside>

  <footer>
    <address>...</address>
  </footer>
</body>

Code Examples

Notice that <header> and <footer> appear twice: once for the whole page, and once nested inside the <article> to introduce and close out just that post. Each usage is scoped to its nearest sectioning ancestor — the browser and assistive tech understand this automatically.

The visible text can be written however reads best for humans, while the datetime attribute gives software (calendars, search engines, browser extensions) an exact, unambiguous value to parse.

<body>
  <header>
    <h1>Dev Notes</h1>
    <nav>
      <a href="/">Home</a>
      <a href="/archive">Archive</a>
      <a href="/about">About</a>
    </nav>
  </header>

  <main>
    <article>
      <header>
        <h2>Why Semantic HTML Matters</h2>
        <p>By Priya Shah — <time datetime="2026-09-10">Sep 10, 2026</time></p>
      </header>
      <p>Semantic elements describe meaning, not just layout...</p>
      <footer>
        <p>Filed under: Accessibility, HTML</p>
      </footer>
    </article>

    <section>
      <h2>More From This Author</h2>
      <p>...</p>
    </section>
  </main>

  <aside>
    <h2>Related Reading</h2>
    <p>...</p>
  </aside>

  <footer>
    <address>
      Contact: <a href="mailto:[email protected]">[email protected]</a>
    </address>
    <p>&copy; 2026 Dev Notes</p>
  </footer>
</body>
<p>Published on <time datetime="2026-09-14">September 14, 2026</time>.</p>
<p>The event starts at <time datetime="2026-09-20T18:30">6:30 PM on Sep 20</time>.</p>

Semantic page landmarks

Screen readers expose this exact structure as jumpable landmarks: a user can leap straight to "main" or "navigation" without reading the whole page.

+-------------------------------+
|             HEADER            |
+-------------------------------+
|              NAV              |
+---------------+---------------+
|     MAIN      |     ASIDE     |
| +-----------+ |               |
| | ARTICLE   | |               |
| +-----------+ |               |
| +-----------+ |               |
| | SECTION   | |               |
| +-----------+ |               |
+---------------+---------------+
|             FOOTER            |
+-------------------------------+

Important Rules

Use exactly one <main> element per page, and never nest it inside <article>, <aside>, header, footer, or another <main>.

<header> and <footer> are scoped to their nearest sectioning ancestor — they can repeat once per <article> in addition to the page level.

Use <article> for content that makes sense extracted and distributed on its own; use <section> for a themed grouping that only makes sense in context.

A <section> should generally have its own heading (h1-h6); a heading-less group of content is usually better left as a plain <div>.

Reach for <div> only when no semantic element fits — it's the fallback, not the default.

In practice

Large news sites like the structure in this lesson almost exactly: a <header> with the masthead and <nav>, a <main> containing one <article> per story (each independently shareable and syndicated via RSS), an <aside> for "related stories" or ads, and a site-wide <footer> with an <address> for contact and legal links. Accessibility audits (and automated tools like Lighthouse) explicitly check for a single <main>, meaningful landmarks, and a logical heading structure — all of which come for free once you build with semantic elements from the start.

<div class="header"><div class="nav">...</div></div> Class names look descriptive to humans but are invisible to assistive technology and search engines — they carry zero semantic meaning to a machine.

Wrapping content in <section> purely for CSS styling hooks, without a real thematic grouping or heading, misuses the element — use <div> for pure styling containers.

[Identify the Error] A developer wraps their entire page's main content area in two separate <main> elements — one for a "featured post" and one for "recent posts" — reasoning that each needs to be a primary content block. What is wrong with this approach? A. Nothing is wrong; a page can have as many <main> elements as it has primary content blocks. B. A page should contain only one visible <main> element; both blocks should instead go inside a single <main>, using <section> or <article> to separate them. C. <main> can only be used once per website, not once per page. D. <main> is a deprecated element and neither block should use it.

B. A page should contain only one visible <main> element; both blocks should instead go inside a single <main>, using <section> or <article> to separate them. — There should be exactly one visible <main> per page. Multiple distinct content blocks within that main content area should be separated using <section> or <article> nested inside the single <main>, not multiple <main> elements.

Take a page currently built as nested <div>s with classes like "header", "sidebar", and "main-content", and rewrite it using header, nav, main, aside, and footer. Add one <article> for a piece of standalone content and mark its publish date with <time>.

See the 'A blog page built with semantic elements' example above for a complete reference structure.

Start from the outside in: page header first, then main content area, then aside, then page footer. Only after the skeleton is right, decide whether content inside main needs section or article.