Problem Solved

HTML · semantic

Home › Courses › HTML › Problems › Semantic HTML
📄 Concept · 3 min read

What is semantic HTML?
<header> over <div>.

Semantic HTML means using the element that describes what the content is, not just how it looks. A <header> for a page header. A <nav> for navigation. An <article> for a self-contained piece of content. The browser, search engines, and screen readers all understand it. A <div> tells them nothing. This page covers the elements, the before/after, and the rule for when to keep <div>.

Short answer: Use <header>, <nav>, <main>, <section>, <article>, <aside>, and <footer> instead of <div> for page structure. It improves SEO (search engines weight the content), accessibility (screen readers can jump between regions), and readability (the next developer understands the structure at a glance). Use <div> only for styling hooks when no semantic element fits.

✅ The semantic elements

What each one means and when to use it.

<header>

Introductory content for a page or section. Logo, title, hero. Can be used inside <article> too.

<nav>

A block of navigation links. The main menu. Not every group of links — just the primary navigation.

<main>

The dominant content of the page. One per page. Excludes headers, footers, and sidebars.

<article>

Self-contained content that makes sense on its own: a blog post, a forum reply, a product card.

<section>

A thematic grouping of content. Usually has a heading. Don't use it as a generic wrapper — use <div> for that.

<aside>

Content tangentially related to the main content: a sidebar, a pull quote, related links.

<footer>

Footer for a page or section. Copyright, author info, related links.

<figure> / <figcaption>

Self-contained media with a caption: an image, a diagram, a code snippet. The caption describes it.

✅ Before and after

The same layout, two ways.

non-semantic.html
<div class="header">
<div class="logo">My Site</div>
<div class="nav">
<a href="/">Home</a>
<a href="/about">About</a>
</div>
</div>
<div class="main">
<div class="post">
<div class="post-title">Hello</div>
<div class="post-body">Content here.</div>
</div>
</div>
<div class="footer">© 2026</div>
❌ No semantics — the browser sees a wall of divs.
❌ Screen readers can't jump between regions.
❌ Search engines can't identify the main content.
❌ The next developer has to read the class names to understand the structure.
semantic.html
<header>
<h1>My Site</h1>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<article>
<h2>Hello</h2>
<p>Content here.</p>
</article>
</main>
<footer>© 2026</footer>
✅ The browser knows the structure.
✅ Screen readers can jump to header, main, nav, footer.
✅ Search engines identify the article as primary content.
✅ The next developer reads it at a glance.

Same CSS works

Semantic elements are just elements. Style them with CSS exactly like <div>. No behavior is lost.

Same layout works

Display: block by default — same as <div>. Flexbox, grid, positioning — all apply identically.

Headings matter

Each semantic region should have a heading. <h1> once per page, <h2> for sections, <h3> inside.

ARIA only when needed

If a semantic element exists, use it — don't add role="navigation" to <nav>. Native wins.

⚠️ Common mistakes

The semantic mistakes that cost real time.

1. Using <div> for everything

The classic — every element is a div with a class name. Fix: use the semantic element, keep the class for styling.

2. Multiple <main> on one page

Only one <main> per page. Fix: if you have multiple "main" regions, use <section> inside a single <main>.

3. <section> as a generic wrapper

<section> is thematic — it should have a heading. Fix: use <div> for styling-only wrappers.

4. Skipping heading levels

<h1> → <h3> skips h2. Fix: step by one level. Headings convey structure to screen readers.

5. <nav> on every link group

Not every group of links is navigation. Fix: reserve <nav> for primary navigation — the main menu.

6. Adding ARIA to semantic elements

<nav role="navigation"> — redundant. Fix: only add ARIA when no native element fits.

7. <article> inside <article> without reason

Nested articles are valid — but only when each is self-contained. Fix: use <section> for grouped content inside an article.

8. Forgetting <header> / <footer> inside <article>

An article's title and metadata go in its own <header>. Fix: header, content, footer inside the article.

❓ Frequently asked

What is semantic HTML?

Semantic HTML means using the element that describes what the content is, not just how it looks. A header for a page header, a nav for navigation, an article for a self-contained piece of content. The browser, search engines, and screen readers all understand it. A div tells them nothing. Use semantic elements for page structure, and use div only for generic styling containers when no semantic element fits.

Does semantic HTML improve SEO?

Yes, indirectly. Search engines weight the content inside semantic elements more heavily — a heading inside header is treated as a page title, a block inside article is treated as the main content. Crawlers also use the structure to understand relationships between sections. The improvement is not a ranking factor by itself, but it makes the content easier for search engines to parse and index correctly.

What is the difference between section and article?

An article is self-contained — it makes sense on its own, like a blog post or a product card. A section is a thematic grouping that is part of a larger whole — like the comments section of a blog post, or the pricing section of a landing page. Use article when the content could stand alone. Use section when it needs the surrounding context. Both should have a heading.

Can I still use div?

Yes. Div is still correct when you need a generic container for styling — for example, a flex wrapper around two cards. The rule is to use the most specific element that describes the content. If a semantic element fits, use it. If none fits, use div. The mistake is using div for everything, not using div for anything.

🔗 Related

← All HTML problems
Problem solved · HTML