Skip to content
academia.sh

Lesson 13 / 25

Semantic Section Tags

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

Contents

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.

// 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.

<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.

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.

<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

<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.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close