Semantic HTML: Why <div> Isn't Always the Answer
If you're new to web development, there's a good chance you've written a page that looks something like this:
<div class="header">
<div class="nav">
<div class="nav-item">Home</div>
<div class="nav-item">About</div>
</div>
</div>
<div class="content">
<div class="title">My Blog Post</div>
<div class="text">Some content here...</div>
</div>
<div class="footer">© 2026</div>
It works. The browser renders it, the CSS applies, everything looks fine on screen. So what's the problem?
The problem with "div soup"
A <div> tells the browser (and anyone reading your code) absolutely nothing about what that piece of content is. It's a generic box — useful, but meaningless on its own. When your entire page is built out of <div>s with class names doing all the work, you lose information that HTML was designed to carry for free.
That missing information matters to more than just other developers:
- Screen readers (software blind and low-vision users rely on to navigate a page) announce elements by their role. A
<nav>gets announced as "navigation" — a<div class="nav">gets announced as nothing at all. - Search engines use your HTML structure to understand what's important on the page. A
<h1>and an<article>carry weight that a<div>doesn't. - Browsers give some elements free behavior — a
<button>is focusable and works with the keyboard out of the box; a<div>styled to look like a button is not, unless you rebuild that behavior yourself.
What "semantic" actually means
Semantic HTML just means: use the tag that describes what the content is, not just how it should look.
Here's the same layout from before, written semantically:
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<article>
<h1>My Blog Post</h1>
<p>Some content here...</p>
</article>
</main>
<footer>© 2026</footer>
Same visual result once you add CSS — but now the structure itself explains the page, with zero extra effort.
Tags worth knowing
| Tag | Use it for |
|---|---|
<header> | Introductory content — usually a logo, title, or nav at the top of a page or section |
<nav> | A block of navigation links |
<main> | The primary content of the page (only one per page) |
<article> | A self-contained piece of content — a blog post, a comment, a product card |
<section> | A thematic grouping of content, usually with its own heading |
<aside> | Content tangentially related to the main content — a sidebar, a callout |
<footer> | Closing content — copyright, links, contact info |
<button> | Anything the user clicks to do something (submit a form, open a menu) |
<a> | Anything the user clicks to go somewhere (a link) |
A rule of thumb
Before reaching for <div>, ask: "Is there a tag that already describes this?" If you're building a button, use <button>. If you're linking to another page, use <a>. If you're grouping a form's related fields, use <fieldset>.
<div> (and its inline cousin <span>) still have a real job: they're for when there genuinely is no semantic meaning to express — a wrapper you need purely for styling or layout. That's a legitimate use. The goal isn't to eliminate <div> — it's to stop reaching for it by default.
Why this pays off early
You don't need to master accessibility or SEO to benefit from this habit. Writing semantic HTML from day one means:
- Your CSS gets simpler, because tags like
<nav>and<button>already come with sensible default behavior. - Your code is easier to read — six months from now,
<article>tells a faster story than<div class="post-wrapper">. - You're not accumulating a debt you'll have to pay down later, when a client or employer asks you to make the site accessible.
Next time you write <div>, pause for a second and ask what that content actually is. More often than you'd expect, HTML already has a word for it.