4 min read
On this page

Semantic Markup

HTML Is for Structure, Not Styling

HTML describes what content is, not what it looks like. A <h1> is a top-level heading because of its meaning, not because it renders big and bold. A <nav> is navigation because of its role, not because of where it sits on the page.

When you use a <div> for everything, you tell the browser and assistive technologies nothing about your content. When you use semantic elements, you communicate structure, meaning, and relationships.

<!-- This tells the browser nothing -->
<div class="header">
  <div class="nav">
    <div class="nav-item">Home</div>
    <div class="nav-item">About</div>
  </div>
</div>

<!-- This tells the browser exactly what everything is -->
<header>
  <nav aria-label="Main">
    <a href="/">Home</a>
    <a href="/about">About</a>
  </nav>
</header>

Both can be styled to look identical. The difference is invisible to sighted users but critical for screen readers, search engines, and anyone reading or maintaining the code.

The Semantic Elements

Document Structure

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Page Title</title>
</head>
<body>
  <header>
    <nav aria-label="Main">...</nav>
  </header>

  <main>
    <article>
      <h1>Article Title</h1>
      <p>Content...</p>
    </article>

    <aside>
      <h2>Related Links</h2>
      ...
    </aside>
  </main>

  <footer>
    <p>Copyright 2026</p>
  </footer>
</body>
</html>

Element Reference

Element Purpose When to Use
<header> Introductory content or navigation Page header, article header
<nav> Navigation links Main nav, sidebar nav, footer nav
<main> Dominant content of the page Once per page, direct child of <body>
<article> Self-contained, independently distributable content Blog post, product card, comment
<section> Thematic grouping of content Chapters, tabs, grouped content
<aside> Content tangentially related to surrounding content Sidebars, callouts, related links
<footer> Footer for nearest sectioning ancestor Page footer, article footer

article vs section

An <article> should make sense on its own. Could you syndicate it in an RSS feed? Put it on another page? Then it is an article.

A <section> is a thematic grouping that is part of something larger. It usually has a heading.

<!-- A blog post is an article -->
<article>
  <h2>Understanding Flexbox</h2>
  <p>Flexbox is a one-dimensional layout model...</p>

  <!-- Sections within the article -->
  <section>
    <h3>Main Axis vs Cross Axis</h3>
    <p>...</p>
  </section>

  <section>
    <h3>Common Patterns</h3>
    <p>...</p>
  </section>
</article>

When to Use div

Use <div> when no semantic element fits. It is a generic container for styling or scripting purposes. There is no shame in using <div> -- just make sure you are not using it when a semantic element would be more appropriate.

<!-- div for styling wrapper -- no semantic meaning needed -->
<div class="card-grid">
  <article class="card">...</article>
  <article class="card">...</article>
  <article class="card">...</article>
</div>

Headings Hierarchy

Headings (<h1> through <h6>) create a document outline. They are not font sizes -- they are a hierarchy of importance.

Rules

  1. Use one <h1> per page (the page title or main topic)
  2. Do not skip levels: <h1> then <h3> without <h2> is wrong
  3. Each section should start with the appropriate heading level
  4. Headings should describe the content that follows
<h1>Web Fundamentals Guide</h1>

  <h2>HTML</h2>
    <h3>Semantic Markup</h3>
    <h3>Forms</h3>

  <h2>CSS</h2>
    <h3>Layout</h3>
      <h4>Flexbox</h4>
      <h4>Grid</h4>
    <h3>Styling</h3>

Screen reader users navigate by headings. A user can pull up a list of all headings on the page and jump directly to the section they need. Skipped levels or meaningless headings break this navigation.

<!-- Bad: heading used for font size -->
<h4 class="small-text">Posted 3 days ago</h4>

<!-- Good: use CSS for font size, use the right heading level -->
<p class="meta">Posted 3 days ago</p>

Inline Semantic Elements

Semantics go beyond page structure. Inline elements convey meaning within text.

<!-- Emphasis (spoken stress) -->
<p>You <em>must</em> submit the form before midnight.</p>

<!-- Strong importance -->
<p><strong>Warning:</strong> This action cannot be undone.</p>

<!-- Time (machine-readable) -->
<p>Published on <time datetime="2026-04-18">April 18, 2026</time></p>

<!-- Abbreviation -->
<p>The <abbr title="World Wide Web Consortium">W3C</abbr> maintains web standards.</p>

<!-- Code -->
<p>Use the <code>addEventListener</code> method to attach event handlers.</p>

<!-- Quotation -->
<blockquote cite="https://www.w3.org/WAI/">
  <p>The power of the Web is in its universality.</p>
</blockquote>

<!-- Marked/highlighted text -->
<p>Search results for "flexbox": <mark>flexbox</mark> is a layout model...</p>

Lists

Use the right list type for the content.

<!-- Ordered: sequence matters -->
<ol>
  <li>Preheat oven to 350F</li>
  <li>Mix dry ingredients</li>
  <li>Add wet ingredients</li>
</ol>

<!-- Unordered: sequence does not matter -->
<ul>
  <li>Flour</li>
  <li>Sugar</li>
  <li>Butter</li>
</ul>

<!-- Description list: term-description pairs -->
<dl>
  <dt>HTML</dt>
  <dd>HyperText Markup Language -- defines the structure of web content</dd>

  <dt>CSS</dt>
  <dd>Cascading Style Sheets -- controls the visual presentation</dd>
</dl>

Why Semantics Matter

Accessibility

Screen readers announce elements based on their semantics. A <nav> is announced as "navigation." A <main> lets users skip directly to the primary content. A <button> is announced as interactive and can be activated with Enter or Space. A <div> with an onclick handler is announced as nothing.

SEO

Search engines use semantics to understand page structure. The content inside <main> is the primary content. <h1> signals the page topic. <article> boundaries help search engines identify distinct pieces of content. <nav> tells crawlers where the navigation links are.

Maintainability

When you read semantic HTML (<header>, <main>, <article>), you understand the page without looking at CSS. Div-based markup (<div class="top-bar">) requires you to read class names and trust they have not been misused. Semantic elements always mean what they say.

A Real-World Example

A product listing page with proper semantics:

<body>
  <header>
    <a href="/" aria-label="Home">ShopName</a>
    <nav aria-label="Main">
      <ul>
        <li><a href="/products">Products</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <h1>Running Shoes</h1>

    <section aria-label="Product listing">
      <article class="product-card">
        <h2>Trail Runner Pro</h2>
        <p>Lightweight trail shoe with aggressive tread.</p>
        <p><strong>$129.99</strong></p>
        <a href="/products/trail-runner-pro">View Details</a>
      </article>

      <article class="product-card">
        <h2>Road Racer Elite</h2>
        <p>Competition road shoe with carbon plate.</p>
        <p><strong>$179.99</strong></p>
        <a href="/products/road-racer-elite">View Details</a>
      </article>
    </section>

    <aside>
      <h2>Filter by Category</h2>
      <nav aria-label="Product filters">
        <ul>
          <li><a href="?cat=trail">Trail</a></li>
          <li><a href="?cat=road">Road</a></li>
          <li><a href="?cat=track">Track</a></li>
        </ul>
      </nav>
    </aside>
  </main>

  <footer>
    <p>Copyright 2026 ShopName</p>
  </footer>
</body>

Common Pitfalls

  • Div soup: Wrapping everything in <div> elements when semantic alternatives exist. Ask yourself: "What is this content?" before choosing an element.
  • Using headings for font size: <h4> should not be chosen because you want smaller text. Use CSS for visual sizing, headings for document structure.
  • Skipping heading levels: Going from <h2> to <h4> breaks the document outline. Screen reader users rely on the hierarchy.
  • Multiple <main> elements: There should be one <main> per page. It represents the dominant content.
  • Using <section> instead of <div>: A <section> without a heading is usually a <div> in disguise. If it does not represent a thematic grouping, use <div>.
  • Forgetting lang attribute: <html lang="en"> tells screen readers which language to use for pronunciation. Missing it causes garbled speech synthesis.
  • Making non-interactive elements clickable: Adding onclick to a <div> or <span> instead of using a <button> or <a>. These lack keyboard support and screen reader announcements.

Key Takeaways

  • HTML describes structure and meaning, not appearance
  • Semantic elements (header, nav, main, article, section, aside, footer) communicate purpose to browsers, assistive technologies, and search engines
  • Headings form a hierarchy -- use one <h1> per page and do not skip levels
  • Use <article> for self-contained content and <section> for thematic groupings
  • Use <div> only when no semantic element fits
  • Inline semantics matter too: <strong>, <em>, <time>, <code>, <abbr>
  • Semantic HTML is more accessible, more SEO-friendly, and more maintainable than div soup
  • The right element is always better than a div with a class name