Semantic HTML.
Elements that mean something.
A div class="header" and a header tag look the same in a browser. But a screen reader, a search engine, and every developer reading your code treat them completely differently. Semantic HTML is the difference between a page that works and a page that works for everyone. This is the lesson that separates amateur HTML from professional HTML.
Semantic HTML means using elements whose names describe their purpose: header for intro content, nav for navigation, main for primary content, article for self-contained pieces, section for thematic groupings, aside for tangents, footer for closing content. A div is a fallback when none of these fit. These 8 elements cover 90% of real page structure.
Before this lesson: complete Lesson 1. You need to be comfortable writing tags and opening files in a browser.
🎯 Why semantic HTML matters
Three reasons. All of them matter more than the extra typing costs.
1. Accessibility
Screen readers scan the page and announce landmarks: "navigation", "main content", "article". A page built with divs is announced as "generic container, generic container, generic container" — no structure. A page built with semantic elements is navigable. This is required for WCAG compliance and simple human decency.
2. SEO
Google's crawler reads HTML the same way a screen reader does. Semantic elements help Google identify what's navigation vs content vs promotional — which helps it rank the right elements. It also improves accessibility metrics Google tracks (Core Web Vitals, mobile experience).
3. Maintainability
Reading <nav class="sidebar-nav"> tells you exactly what it is. Reading <div class="sidebar"> requires opening the CSS file to figure out what it does. Six months from now, you are a stranger to your own code — semantic elements make you less of a stranger.
The trade is small: semantic elements are often one word longer than div. The gain is large: accessible structure, better SEO, and code that future-you can read. There is no downside to using them. There is a big downside to not using them.
🧱 The 7 elements you'll use constantly
Each one has a specific meaning. Learn what each is for, and the rest of HTML structure becomes obvious.
<header>
Introductory content for a page or section. Usually contains the logo, title, and sometimes navigation. Can appear at the top of the page OR inside an article — each article can have its own header.
<nav>
Navigation links. Primary site navigation, table of contents, previous/next links. Not every group of links is a nav — just the ones that are for navigating.
<main>
The primary content of the page — what the page is about. Exactly one per page. Excludes headers, footers, sidebars, and navigation. Screen readers let users jump directly to main.
<article>
Self-contained content that makes sense on its own. A blog post, a forum thread, a product review, a comment. If you could paste it into another page and it would still make sense, it's an article.
<section>
A thematic grouping of content, usually with a heading. Chapters within an article, tab panels, distinct page areas. Rule: if it doesn't have a natural heading, it's probably not a section — use a div.
<aside>
Content tangentially related to the main content. Sidebars, pull quotes, related links, ads, author bios. Content that could be removed without breaking the main flow.
<footer>
Closing content for a page or section. Copyright, contact links, related links, author info. Can appear at the bottom of the page OR at the end of an article.
<div>
The fallback. A generic container with no meaning. Use it when no semantic element fits — for pure styling groupings, layout wrappers, or structural anchors with no other semantic role.
Don't over-nest semantic elements. A section inside a section inside a section is confusing and rarely correct. If you're three levels deep, the middle one is probably a div. Semantic elements are for meaningful structure, not for grouping everything.
⚖️ div vs section — the rule
The most-asked semantic HTML question. The answer is clearer than it looks.
| Use case | Element | Why |
|---|---|---|
| Has a heading, forms a thematic unit | section | Describes a chapter-like grouping |
| Self-contained (blog post, review) | article | Would make sense on its own |
| Page navigation | nav | Describes navigation, not generic links |
| Page intro (logo, site title) | header | Describes the page's opening |
| Page main content | main | Describes primary content, one per page |
| Sidebar, related content | aside | Describes tangential content |
| Footer (copyright, links) | footer | Describes closing content |
| Pure layout wrapper, no meaning | div | Generic container for styling |
The heading test. Ask: "does this grouping have a natural heading?" If yes, it's a section. If no, it's a div. That single question resolves 95% of div-vs-section decisions.
The paste test. Ask: "could I copy this into a different page and it would still make sense?" If yes, it's an article. If no, it's a section or div.
❌ Before: div soup
This is what non-semantic HTML looks like. It works visually, but it has no meaning.
<div class="header"> <div class="logo">My Site</div> <div class="nav"> <div class="nav-link"><a href="/">Home</a></div> <div class="nav-link"><a href="/about">About</a></div> </div> </div> <div class="main"> <div class="article"> <div class="article-title">My First Post</div> <div class="article-body"> <p>Content here...</p> </div> </div> </div> <div class="sidebar"> <div class="sidebar-title">Related</div> <div class="sidebar-link"><a href="/post-1">Post 1</a></div> </div> cleavage <div class="footer"> <div>© 2026</div> </div>
This page renders fine. A sighted user sees a normal website. But a screen reader sees: "generic container, generic container, link, link, generic container..." — with no indication of what's navigation, what's content, what's a sidebar. Google sees the same thing. Every semantic cue is missing.
✅ After: semantic HTML
Same visual result, same CSS. Completely different meaning.
<header> <h1>My Site</h1> <nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> </ul> </nav> </header> <main> <article> <h2>My First Post</h2> <p>Content here...</p> </article> </main> <aside> <h3>Related</h3> <ul> <li><a href="/post-1">Post 1</a></li> </ul> </aside> <footer> <p>© 2026</p> </footer>
Screen readers
Now announce: "banner" (header), "navigation", "main", "article", "complementary" (aside), "contentinfo" (footer). Users can jump between landmarks instantly — like tabbing between sections in a Word document.
Search engines
Now know exactly which content is navigation (lower priority) vs main content (higher priority) vs sidebar (lower priority). The main content gets weighted accordingly.
Other developers
Now read the structure at a glance. "Oh, the header has nav, main has an article, there's a sidebar and footer" — all from the tags, no CSS needed.
🏗️ A real page structure
The layout that 90% of real websites follow. Learn it once, apply it everywhere.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Blog</title> </head> <body> <header> <h1>My Blog</h1> <nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav> </header> <main> <article> <header> <h2>Why I Love HTML</h2> <p><time datetime="2026-10-24">October 24, 2026</time> by Alice</p> </header> <section> <h3>The structure</h3> <p>HTML gives structure to content...</p> </section> <section> <h3>The accessibility</h3> <p>Semantic elements help everyone...</p> </section> <footer> <p>Thanks for reading!</p> </footer> </article> <aside> <h3>Related Posts</h3> <ul> <li><a href="/post-1">HTML Basics</a></li> <li><a href="/post-2">CSS Introduction</a></li> </ul> </aside> </main> <footer> <p>© 2026 My Blog. All rights reserved.</p> </footer> </body> </html>
Two headers
The page has a top-level header (site title + nav). The article has its own header (title + date). Both are correct — header can appear anywhere.
Two footers
The article has a footer (thanks for reading). The page has a footer (copyright). Both are correct — same rule as header.
One main
Only one main per page, containing the primary content. Screen readers let users jump directly to it, so multiple mains would be confusing.
Sections inside article
The article has two section elements, each with an h3. That's a thematic grouping inside a self-contained piece — exactly what section is for.
This is the layout every blog, docs site, and content site uses. Header, main (article + optional aside), footer. Once you have this pattern memorized, you can structure any page — a product page, a docs chapter, a portfolio. The elements change based on content, but the shape is the same.
🏆 Challenge
Two tasks. One fixes bad HTML. One builds good HTML.
Task 1 — Fix the div soup
Take the "bad.html" example from this lesson (the div soup version). Rewrite it using semantic elements. Keep all the text content the same. Change every div to the appropriate semantic element.
Compare your version to the "good.html" example. If they're similar, you've got it. If not, look at what's different.
Task 2 — Build a semantic page
Build a single-page site for a fictional product with this structure:
1. header — site title, nav with 3 links
2. main containing:
• an article about the product with 2 sections
• an aside with related products
3. footer — copyright + contact link
Use every element correctly. Add alt text to any images. Once you're done, open the page in your browser and in a screen reader (VoiceOver on Mac, NVDA on Windows). The screen reader should announce the structure — "banner", "navigation", "main", "article", etc.
⚠️ Common mistakes
The semantic HTML errors that catch every beginner.
div class="header", div class="nav", div class="button" — this is div soup. If the class name describes a semantic element, use that element instead. Fix: header, nav, button.
One main per page — the primary content area. Multiple mains confuse screen readers. If you need multiple content areas, wrap them in article or section inside the single main.
h1 → h4 to get a specific font size. Fix: use the correct heading level (h1 → h2 → h3) and change the size with CSS. Headings define document outline, not visual appearance.
A section is a thematic grouping — it should have a heading that identifies what the grouping is. If there's no natural heading, it's a div, not a section.
Social links in the footer aren't "navigation" in the semantic sense. Related-posts links in an aside aren't nav either. Use nav only for actual navigation — primary site nav, breadcrumbs, table of contents, pagination.
nav header — the header inside nav describes the nav, not the page. This is legal but often confusing. Keep header/footer at the page or article/section level, not inside nav.
Not every content block is an article. An article is self-contained — could be syndicated to another site. A "Terms of Service" section inside a page isn't an article; it's a section of the page.
aside is for content tangentially related to the main content — a sidebar, a pull quote, related links. Using aside for the "contact form" on a contact page (that IS the main content) is wrong — the form should be in main.
➡️ What's next
You know how to structure a page. Next: the three elements that appear on every single one.
❓ Frequently asked questions
What is semantic HTML?
Semantic HTML means using elements that describe their meaning, not just their appearance. header instead of div class='header', nav instead of div class='nav', button instead of div onclick. The element name tells you and every other program what's inside.
What is the difference between div and section?
div is a generic container with no semantic meaning — a fallback. section is a thematic grouping of content, usually with a heading. If the content has a natural heading, it's a section. If it's just grouping for styling, it's a div.
What is the difference between article and section?
An article is self-contained — could be syndicated to another site (blog post, forum thread, review). A section is a thematic grouping within a larger context (chapter within an article, tabs within a page). Articles can contain sections.
Should I use header inside every section?
Yes — you can use header inside any section or article to group that section's heading and intro. A page usually has one main header at the top, but each article or section can have its own header with the article title.
Can I use multiple main elements?
No. Only one main element per page. It contains the primary content — what the page is fundamentally about. Screen readers let users jump directly to main, so having multiple is confusing.
Why does semantic HTML matter for SEO?
Google's crawler reads HTML the same way a screen reader does. Semantic elements help Google identify what's navigation vs content vs promotional. It also improves accessibility metrics Google tracks.
Do I need semantic HTML if I'm using CSS classes?
Yes. CSS classes only affect appearance — semantic elements affect meaning. A div class='header' looks the same as header to a browser, but screen readers and search engines read them differently. Both matter; they solve different problems.
How do I test if my HTML is semantic?
Two ways: (1) open the page in a screen reader (VoiceOver on Mac, NVDA on Windows) — you should hear landmarks announced. (2) Check the accessibility tree in Chrome DevTools → Elements → Accessibility. If you see "generic" repeated many times, you've got div soup.