Semantic tags describe the meaning of content, not just its appearance. A browser won’t visually distinguish <div> from <article> — both are block-level. But a search engine, a screen reader, and the next developer who opens your code will instantly understand the page structure.
What semantics means in HTML
Compare two versions of the same markup:
<!-- No semantics — everything is a div -->
<div class="header">
<div class="nav">...</div>
</div>
<div class="main">
<div class="post">...</div>
<div class="sidebar">...</div>
</div>
<div class="footer">...</div>
<!-- With semantics -->
<header>
<nav>...</nav>
</header>
<main>
<article>...</article>
<aside>...</aside>
</main>
<footer>...</footer>
The second version communicates structure through the tags themselves, not through class names.
The core semantic tags
<header>
The introductory block of a page or section. Typically contains the logo, site title, and primary navigation.
<header>
<a href="/" class="logo">DevBlog</a>
<nav>
<ul>
<li><a href="/posts/">Articles</a></li>
<li><a href="/about/">About</a></li>
</ul>
</nav>
</header>
<header> can appear inside <article> — then it’s the header of that specific article, not the whole site.
<nav>
The block of primary navigation. Not every group of links is a <nav> — only those that provide navigation around the site or page.
<nav aria-label="Main menu">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/posts/">Articles</a></li>
<li><a href="/tags/">Tags</a></li>
</ul>
</nav>
<main>
The main, unique content of the page. There should be only one <main> on a page. The header, footer, and sidebar don’t belong inside <main>.
<main>
<!-- Everything unique to this page -->
</main>
<article>
A self-contained, independent piece of content: a blog post, an article, a product card, a comment. It should make sense if pulled out of context.
<article>
<header>
<h2><a href="/posts/asyncio/">The Complete asyncio Guide</a></h2>
<time datetime="2025-03-15">March 15, 2025</time>
</header>
<p>We explore the event loop, coroutines, and practical patterns...</p>
<footer>
<a href="/posts/asyncio/">Read more</a>
</footer>
</article>
<section>
A thematic section of content. Unlike <article>, it’s not self-contained — it’s part of a larger whole.
<section id="recent-posts">
<h2>Recent Articles</h2>
<!-- post cards -->
</section>
<section id="popular-tags">
<h2>Popular Tags</h2>
<!-- tag cloud -->
</section>
Each <section> should ideally start with a heading.
<aside>
Content tangentially related to the main content: sidebar, ad block, “Related articles” links, pull quotes.
<aside>
<h3>Related articles</h3>
<ul>
<li><a href="/posts/generators/">Python Generators</a></li>
<li><a href="/posts/contextmanager/">Context Managers</a></li>
</ul>
</aside>
<footer>
The footer of a page or section: copyright, links, contact information.
<footer>
<p>© 2025 DevBlog. Built with Python.</p>
<nav aria-label="Footer links">
<a href="/privacy/">Privacy</a>
<a href="/rss.xml">RSS</a>
</nav>
</footer>
<time>
A machine-readable date and time. The datetime attribute holds the standardised format:
<time datetime="2025-03-15">March 15, 2025</time>
<time datetime="2025-03-15T10:30:00+00:00">March 15 at 10:30</time>
Why this matters
| Reason | Explanation |
|---|---|
| SEO | Google better understands content structure |
| Accessibility | Screen readers present a list of landmarks (nav, main, aside) to users |
| Code readability | Structure is clear without inspecting class names |
| Performance | None — semantics don’t affect speed |
Full example: DevBlog page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>DevBlog — a Python developer's notes</title>
</head>
<body>
<header>
<a href="/" class="logo">DevBlog</a>
<nav aria-label="Main menu">
<ul>
<li><a href="/posts/">Articles</a></li>
<li><a href="/about/">About</a></li>
</ul>
</nav>
</header>
<main>
<section id="recent-posts">
<h1>Recent Articles</h1>
<article>
<header>
<h2><a href="/posts/asyncio/">The asyncio Guide</a></h2>
<time datetime="2025-03-15">March 15, 2025</time>
</header>
<p>Event loop, coroutines, and practical patterns.</p>
</article>
<article>
<header>
<h2><a href="/posts/pydantic-v2/">Pydantic v2: what's new</a></h2>
<time datetime="2025-02-28">February 28, 2025</time>
</header>
<p>Key changes in Pydantic v2 explained.</p>
</article>
</section>
<aside>
<h2>Tags</h2>
<ul>
<li><a href="/tags/python/">Python</a></li>
<li><a href="/tags/fastapi/">FastAPI</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2025 DevBlog</p>
</footer>
</body>
</html>
Use <div> only when no semantic tag fits. If you’re reaching for <div>, pause and ask: “What is this, semantically?” There’s usually an appropriate tag available.
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!