Back to HTML
HTML
medium
mid

What are semantic HTML elements and why do they matter?

Semantic elements describe meaning, not appearance: <header>, <nav>, <main>, <article>, <section>, <aside>, <footer>, <button>, <figure>, <time>. They give assistive tech landmarks, give browsers built-in keyboard and focus behavior, give SEO structured content signals, and make code self-documenting. Compare <div class='button'> (zero meaning) to <button> (focusable, click+keyboard, disabled state, form participation).

6 min read·~5 min to think through

Definition: Semantic HTML elements convey meaning about their content, not just visual styling. <article> says "this is a self-contained piece of content." <div> says nothing.

The semantic vocabulary

Document structure

  • <header> — introductory content (site header, article header).
  • <nav> — primary navigation links.
  • <main> — the unique main content of the page (one per page).
  • <article> — self-contained content reusable in isolation (blog post, comment).
  • <section> — a thematic grouping, usually with a heading.
  • <aside> — tangentially related content (sidebar, callout).
  • <footer> — closing content (copyright, links).

Text-level

  • <time datetime="2026-05-17"> — machine-readable dates.
  • <address> — contact info for the nearest <article> or <body>.
  • <figure>/<figcaption> — illustration + caption pair.
  • <mark> — highlighted/marked text.
  • <abbr title="…"> — abbreviation with expansion.

Interactive

  • <button> — action trigger.
  • <a href> — navigation.
  • <details>/<summary> — native disclosure widget.
  • <dialog> — native modal.
  • <input>, <select>, <textarea> with <label>.

Why they matter

1. Accessibility (the big one). Screen readers use semantic elements to build a navigation model:

  • "Jump to next landmark" → <nav>, <main>, <aside>.
  • "List all headings" → <h1><h6> hierarchy.
  • "Tab through buttons" → <button> is focusable; <div onClick> is not (until you manually add tabindex, keyboard handlers, role, focus ring…).

2. Built-in behavior. <button>: focusable, activated by Enter/Space, has disabled and type="submit". <details>: native expand/collapse with zero JS. <dialog>: modal stacking + Escape-to-close. Replicating these correctly in divs takes hundreds of lines.

3. SEO. Search engines weight content in <main>, <article> higher than chrome in <nav> and <footer>. <time datetime> lets crawlers extract publish dates. <h1><h6> hierarchy is core to topic understanding.

4. Self-documenting code. Six months later, <article class="post"> tells the next dev what it is. <div class="post"> tells them nothing — and grep-ability is worse.

5. Robustness. Browser default styles for semantic elements are sensible. Reader mode, RSS, print stylesheets, and content extraction tools (Pocket, Instapaper) all key off <article>/<main>. Div soup is invisible to them.

Concrete contrast

html
<!-- Div soup -->
<div class="card">
  <div class="title">My Post</div>
  <div class="meta">By Jane, May 2026</div>
  <div class="body">…</div>
  <div class="btn" onclick="like()">Like</div>
</div>

<!-- Semantic -->
<article>
  <h2>My Post</h2>
  <p>By Jane, <time datetime="2026-05">May 2026</time></p>
  <p>…</p>
  <button type="button" onclick="like()">Like</button>
</article>

Same visual output. Wildly different experience for screen reader, keyboard, search engine, and reader-mode users.

When to use <div> and <span>

When you need a hook for styling/layout with no semantic meaning. A wrapper for a CSS grid item, a span for inline text color. They're the fallbacks, not the defaults.

Follow-up questions

  • What's the difference between <section> and <article>?
  • When should you use <div> instead of a semantic element?
  • How do <header> and <footer> work inside <article>?
  • What does <main> add beyond a styled <div>?

Common mistakes

  • Using <section> as a generic wrapper — it's for thematic groupings with a heading.
  • Multiple <main> elements on one page — there should be exactly one.
  • Using <h1> for visual sizing on inner sections — use <h2>/<h3> and CSS.
  • <button> styled as a link, or <a> with onClick that doesn't navigate — pick the one matching intent.
  • Forgetting <label for> association on form inputs.
  • Replacing <details>/<summary> with custom JS disclosure that lacks keyboard support.

Performance considerations

  • Semantic elements are identical to <div> at the rendering level — same DOM cost, same paint. Wins are in dev velocity, a11y, and SEO. No runtime perf trade-off.

Edge cases

  • <section> without a heading is a smell — use <div> instead.
  • Nested <article> elements are allowed (e.g., a comment is an <article> inside the post's <article>).
  • <header>/<footer> can appear inside <article> (per-article header/footer) — they're not page-singletons.
  • <nav> isn't required for every group of links — only for primary navigation regions.
  • <dialog> needs polyfill for older browsers (IE, very old Safari).

Real-world examples

  • BBC, NYT, Guardian — heavily semantic article markup for reader mode + SEO.
  • GitHub uses landmarks extensively; VoiceOver users can navigate the file tree, content, and sidebar with single shortcuts.
  • MDN itself is a semantic-HTML showcase.

Senior engineer discussion

A senior should distinguish semantic *meaning* from semantic *appearance* (don't pick <h1> for size). They should know the accessibility tree (DevTools → Accessibility panel) reveals what AT actually sees, and that semantic-first design prevents the 'ARIA patch on top of div soup' antipattern. Bonus: knowing that React 19+ semantic-aware features (e.g. <Form>) lean into native HTML semantics rather than reinventing them.

Related questions