---
title: 'Semantic Section Tags'
source: 'https://academia.sh/en/courses/web-fundamentals-and-html/semantic-section-tags'
course: 'Web Fundamentals and HTML'
language: en
updated: '2026-08-17T18:09:33+00:00'
license: 'CC BY-SA 4.0'
---

# Semantic Section Tags

How header, navigation, main content, and footer elements correspond to landmark roles, naming sections, and where a meaningless container belongs.

The previous topic built the document's skeleton: headings, text,
lists, links, tables. None of these declarations name the document's
**sections**. Where does navigation end, where does the main content
start, which part is the footer?

This lesson takes up the elements that answer that question. Their
effect on appearance is close to nothing; what they earn is adding a
**high-level map** to the document.

## What a Sectioning Element Declares

A reader who can see the screen infers sections from the layout: the
strip at the top is the header, the column on the side is navigation,
the area in the middle is content. This inference rests on visual cues
and is not declared in the document itself.

Semantic sectioning elements turn this inference into a
**declaration**. Once the document says "this is navigation," that
information opens up to non-visual tools too: screen reader users can
jump from section to section, reading modes can isolate the main
content, indexers can separate navigation links from content links.

The structure that carries this information is called the
**accessibility tree**. It gets derived from the tree in the Document
Object Model lesson, and gives every element a **role**, a **name**,
and a **state** as a trio. Sectioning elements produce **landmark**
roles in this tree.

## Landmark Roles

The correspondences are defined, and a section is conditional on them.
The script below applies the rules.

```js
// roles.mjs - what landmark role section elements correspond to
const ROLES = {
  header: "banner",       // only at the document's top level
  nav: "navigation",
  main: "main",
  aside: "complementary",
  footer: "contentinfo",  // only at the document's top level
  form: "form",           // only if it has an accessible name
  section: "region",      // only if it has an accessible name
  article: "article",
  div: null,
};

const doc = [
  { tag: "header", depth: 1 },
  { tag: "nav", depth: 2, label: "Main navigation" },
  { tag: "main", depth: 1 },
  { tag: "section", depth: 2, label: "Daily measurements" },
  { tag: "section", depth: 2 },
  { tag: "aside", depth: 2, label: "Station profile" },
  { tag: "div", depth: 2 },
  { tag: "footer", depth: 1 },
  { tag: "footer", depth: 3 },
];

for (const item of doc) {
  let role = ROLES[item.tag];
  if ((item.tag === "header" || item.tag === "footer") && item.depth > 1) role = null;
  if ((item.tag === "section" || item.tag === "form") && !item.label) role = null;
  const suffix = item.label ? ' ("' + item.label + '")' : "";
  console.log(("  ".repeat(item.depth - 1) + item.tag + suffix).padEnd(34), role ?? "— not a landmark");
}

console.log("--- landmark list ---");
const landmarks = doc
  .map((item) => {
    let role = ROLES[item.tag];
    if ((item.tag === "header" || item.tag === "footer") && item.depth > 1) role = null;
    if ((item.tag === "section" || item.tag === "form") && !item.label) role = null;
    return role ? role + (item.label ? ": " + item.label : "") : null;
  })
  .filter(Boolean);
console.log(landmarks.join("\n"));
```

```
header                             banner
  nav ("Main navigation")          navigation
main                               main
  section ("Daily measurements")   region
  section                          — not a landmark
  aside ("Station profile")        complementary
  div                              — not a landmark
footer                             contentinfo
    footer                         — not a landmark
--- landmark list ---
banner
navigation: Main navigation
main
region: Daily measurements
complementary: Station profile
contentinfo
```

The output's last section is the list a screen reader user sees. It is
the document's map, and the user can jump straight to a section from
it.

Three conditions need attention. `header` and `footer` elements
produce a landmark only at the document's **top level**; a footer
inside an article is not a landmark, it is that article's footer. A
`section` element produces a landmark only once it has a **name**; an
unnamed section does not show up in the list. `div` never produces a
landmark, under any condition.

The script's `aside` correspondence reflects the case where the
element sits in the document's main flow. For an `aside` nested inside
an article or a section, the mapping is conditional: counting as a
landmark in that position depends on carrying an accessible name. The
rule is the same one given above for `section`, and the reason is the
same — an unnamed region does not get added to the list, because it
could not be told apart in it.

## The Elements

`header` is an introductory block: a title, a subtitle, a byline. At
the top level, it is the document's introduction; inside an article,
it is that article's introduction.

`nav` carries navigation links. Not every group of links in a document
has to be `nav` — the element marks the document's **primary**
navigation blocks. Links inside a paragraph are not navigation.

`main` is the document's main content, and it occurs **once** in the
document. It contains no navigation, no footer, no repeated content
spread across the whole site; it holds only content specific to that
document.

`aside` is content indirectly related to the main flow: a side note, a
profile box, related links. The test is that the main content does not
lose its meaning once the `aside` gets removed.

`footer` is a section's closing information: author, copyright,
related documents. At the top level, it is the document's footer;
inside an article, it is that article's footer.

## Naming a Section

When more than one landmark of the same kind exists — two navigation
blocks, say — which one is which gets told apart by name. There are
two paths.

```html
<nav aria-label="Main navigation">
  <ul><li><a href="/">Network directory</a></li></ul>
</nav>

<nav aria-labelledby="station-navigation">
  <h2 id="station-navigation">Station sections</h2>
  <ul><li><a href="#measurements">Measurements</a></li></ul>
</nav>
```

`aria-label` writes the name directly; it does not appear in the
document. `aria-labelledby` takes the name from the text of an element
already present in the document, and this is **preferred**: the name
and the visible heading do not drift apart.

When writing the name, the role's name does not get repeated. Writing
`aria-label="Main navigation menu"` gets announced by a screen reader
as "main navigation menu navigation"; the role already comes from the
element.

## The Skip Link

A user navigating by keyboard reaches the main content on every page
by passing through **all** of the navigation links. The structure that
shortens this is a link written as the document's **first focusable
element**.

```html
<body>
  <a href="#main-content" class="skip-link">Skip to main content</a>
  <header>
    <nav aria-label="Site-wide navigation">
      <ul><li><a href="/stations/">Stations</a></li></ul>
    </nav>
  </header>
  <main id="main-content">
    <h1>North Slope Measurement Station</h1>
  </main>
</body>
```

The link usually gets hidden at the presentation layer and becomes
visible only once it gets focused. The target's identifier sits on the
`main` element itself.

## When to Use a Meaningless Container

`div` and `span` elements declare no meaning. Their reason for
existing is that not every grouping is meaningful: centering a box,
giving a background, building a presentation group needs an element,
and that element has to add no false declaration to the document.

The choice criterion is this: does this group say something about the
document's **structure**? If it does, a semantic element gets used; if
not, `div` gets used. Writing `section` purely for presentation adds a
meaningless entry to the landmark list — or, being unnamed, adds
nothing at all, and the element stays pointless.

`div` groups at the block level, `span` groups within text flow. Both
are handles for the presentation layer.

## In the Station Document

```html
<body>
  <a href="#main-content">Skip to main content</a>

  <header>
    <p>Measurement Network</p>
    <nav aria-label="Site-wide navigation">
      <ul>
        <li><a href="/stations/">Stations</a></li>
        <li><a href="/method.html">Measurement method</a></li>
      </ul>
    </nav>
  </header>

  <main id="main-content">
    <h1>North Slope Measurement Station</h1>
    <p>Automatic measurement station built at an elevation of 1840 meters above sea level.</p>

    <section aria-labelledby="measured-quantities">
      <h2 id="measured-quantities">Measured Quantities</h2>
      <ul>
        <li>Temperature</li>
        <li>Relative humidity</li>
      </ul>
    </section>

    <aside aria-labelledby="station-profile">
      <h2 id="station-profile">Station Profile</h2>
      <dl>
        <dt>Installation elevation</dt><dd>1840 m</dd>
        <dt>Measurement interval</dt><dd>10 minutes</dd>
      </dl>
    </aside>
  </main>

  <footer>
    <p>Measurement Network Working Group</p>
  </footer>
</body>
```

The document's landmark list has **five** entries at this point, and
this list is a navigation plane separate from the heading outline
built in the previous topic. The two complement each other: landmarks
give the document's coarse sections, headings give the hierarchy
inside those sections.

## Summary

- Semantic sectioning elements turn section information inferred from
  the visual layout into a declaration in the document, and produce
  landmark roles in the accessibility tree.
- `header` and `footer` produce a landmark only at the document's top
  level; `section` produces one only if it has a name; `div` never
  produces one, under any condition.
- `main` occurs once in the document and carries only content specific
  to that document.
- More than one landmark of the same kind gets told apart by name;
  taking the name from a heading visible in the document is preferred,
  and the role's name does not get written into the name.
- `div` and `span` get used for groupings that declare no meaning;
  writing a semantic element for presentation purposes adds a false
  declaration to the document.

## Next Step

This lesson used `section` as a named section and showed `article` in
the landmark table, but did not open up the distinction between them.
The choice between the two is the most frequently misjudged semantic
decision. The next lesson defines this distinction and gives the test
for whether a section is meaningful on its own.
