DeepFrontend
Practice ArenaBlogSign in
Go Pro
DeepFrontend

Interview-grade learning paths and hands-on practice for mid-to-senior engineers. Master internals, patterns, and system architecture with runnable code.

All systems operational

Core Courses

  • -JavaScript Internals
  • -React Reconciliation
  • -TypeScript rigor
  • -Next.js Caching
  • -Node.js Event Loop
  • -System Design
  • -Web Security
  • -CSS & Page Layouts

Explore

  • Learning Paths
  • Practice Arena
  • Pricing Options
  • HTML Sitemap

Resources

  • Privacy Policy
  • Terms of Service
  • Email Support

© 2026 DeepFrontend. All rights reserved.

Expert learning environments for web engineering teams.

Home/HTML/Semantic HTML
beginner20 min read·Updated Jul 2026

Semantic HTML

Semantic HTML means choosing elements for what they mean, not how they look. It's the foundation everything else — accessibility, SEO, maintainability — is built on top of, and it's one of the most common things interviewers probe for signs of real craftsmanship.

htmlsemanticsaccessibilityseodocument-structure

Knowledge Check

4 questions · pass at 70%

0/4
easymcq

1. Which pair of elements is functionally equivalent to `<div class="btn" onclick="...">` in terms of built-in keyboard accessibility?


Interview Questions

3 questions

Cheatsheet

Download-ready reference
Cheatsheet
Element → Meaning:
  <header>    Introductory content / page or section banner    → role="banner"
  <nav>       Navigation links                                  → role="navigation"
  <main>      Primary content of the page (one per page)         → role="main"
  <article>   Independently distributable content                → role="article"
  <section>   Thematic grouping, usually with a heading           → role="region" (if named)
  <aside>     Tangential content (sidebars, pull quotes)           → role="complementary"
  <footer>    Footer content / metadata                            → role="contentinfo"
  <figure>    Self-contained media + <figcaption>
  <time>      Machine-readable date/time via datetime attribute

Decision checklist before reaching for <div>:
  Is it clickable/interactive?        → <button> or <a href>
  Is it a heading?                    → <h1>–<h6>
  Is it a list of items?              → <ul>/<ol>/<li>
  Is it a labeled form field?         → <label> + <input>/<select>/<textarea>
  Is it a page region (nav/footer)?   → landmark element
  Is it standalone/syndicatable?      → <article>
  Is it a themed grouping w/ heading? → <section>
  None of the above?                  → <div> is correct

Inline semantics:
  <strong>  importance (bold by default, but semantic)
  <em>      stress emphasis (italic by default, but semantic)
  <b>/<i>   purely visual, no semantic weight
  <mark>    highlighted/relevant text
  <code>    inline code
  <time datetime="...">  machine-readable date/time

Quick audit tools:
  Chrome DevTools → Elements → Accessibility pane  → see the computed a11y tree
  validator.w3.org                                  → catches structural errors

Related topics

Accessibility (ARIA)SEO BasicsRequest Lifecycle (browser → server)

On this page

20m
Knowledge CheckInterview QuestionsCheatsheet

Concept#

Semantic HTML is the practice of using elements according to their meaning, not their default appearance. A <button> and a <div onclick="..."> can look identical after CSS, but only one of them tells the browser, assistive technology, and search engines "this is a clickable control." The other is just a rectangle that happens to respond to clicks.

This matters more than it looks like it should, because HTML is read by more than just your CSS:

  • Screen readers build a navigable outline from headings, landmarks, and roles — <nav>, <main>, <h1>–<h6>.
  • Search engines weight content inside <article>, <h1>, and semantic landmarks more heavily than an equivalent <div> soup.
  • Browsers give semantic elements free behavior — <button> is keyboard-focusable and triggers on Enter/Space with zero JavaScript; a <div> gives you none of that.
  • Other engineers (including future you) read the DOM tree to understand the page's structure before reading any CSS or JS.

The document outline#

<body>
  <header>
    <nav>...</nav>
  </header>
 
  <main>
    <article>
      <h1>Post title</h1>
      <section>
        <h2>Section heading</h2>
        <p>...</p







Each landmark element (<header>, <nav>, <main>, <aside>, <footer>) maps to an ARIA landmark role automatically — banner, navigation, main, complementary, contentinfo — for free. A screen reader user can jump straight to <main> with a single keystroke ("skip to main content" is literally built into the element, no skip-link required if you use it correctly).

<div>/<span> vs semantic elements#

<div> and <span> are semantically neutral — they carry no meaning. They're the right choice only when no semantic element fits (a generic styling wrapper, a layout grid cell). If you're reaching for <div> to represent a button, a list, a heading, or a piece of navigation, there's almost always a better element:

Instead ofUse
<div class="button"><button>
<div class="header"><header>
<div class="list"><div>item</div></div><ul><li>item</li></ul>
<div class="link" onclick>

Sectioning elements: <article> vs <section> vs <div>#

This is the distinction most engineers get wrong:

  • <article> — content that's independently distributable and makes sense on its own outside the page (a blog post, a forum comment, a product card in a listing). Ask: "would this make sense in an RSS feed?"
  • <section> — a thematic grouping of content, usually with its own heading, that's part of a larger whole and doesn't stand alone (a chapter, a tab panel, "Reviews" on a product page).
  • <div> — no semantic meaning at all. Use it when you need a wrapper purely for styling/layout and neither of the above applies.
<article>
  <h2>How closures work</h2>
  <section>
    <h3>Lexical scoping</h3>
    <p>...</p>
  </section>
  <section>
    <h3>Common mistakes</h3>
    <p>...</p>

A useful heuristic: if removing the heading from a <section> would make it meaningless, it's correctly used. <section> without a heading is almost always a <div> in disguise.

Inline semantics#

Semantics aren't only about page structure — they apply within a sentence too:

<p><strong>Warning:</strong> this action <em>cannot</em> be undone.</p>
<p>The variable <code>count</code> is <mark>reassigned</mark> on line 12.</p>
<p>Meeting is at <time datetime="2026-07-12T15:00">3pm on July 12th</time>.</p>
<

<strong> and <em> carry semantic weight (importance / stress emphasis) that screen readers announce with a change in tone — <b> and <i> are purely visual (bold/italic) with no meaning. Use <b>/<i> only for stylistic conventions that genuinely have no semantic weight (e.g. a ship's name, a taxonomic term).

Headings form an outline, not a font-size picker#

<!-- Wrong: skipping levels for visual size -->
<h1>Page title</h1>
<h4>Section</h4> <!-- skipped h2, h3 -->
 
<!-- Right: sequential, styled with CSS separately -->
<h1>Page title</h1>
<h2>Section</h2>
<h3>Subsection</h3>

Never choose a heading level because it "looks right" at that font size — style it with CSS. Heading level should reflect document structure, and screen reader users frequently navigate by jumping between headings of a specific level.


Common Mistakes#

1. <div> soup for interactive elements#

<!-- Wrong -->
<div class="btn" onclick="submit()">Submit</div>

Not focusable by keyboard (no Tab stop), not announced as a button by screen readers, doesn't respond to Enter/Space without extra JS, doesn't get :focus-visible styling for free.

<!-- Right -->
<button type="submit">Submit</button>

2. Using <section> as a generic wrapper#

<!-- Wrong — no heading, no distinct theme, just a styling wrapper -->
<section class="flex gap-4">
  <div>Card 1</div>
  <div>Card 2</div>
</section>

If it has no heading and isn't a distinct thematic grouping, it's a <div>.

3. Multiple <h1>s without understanding the outline algorithm#

The HTML5 "outline algorithm" that would have let you nest multiple <h1>s per <section> was never implemented by any browser or screen reader and was removed from the spec. In practice: one <h1> per page, then descend sequentially (<h2>, <h3>...).

4. <a> without href for buttons#

<!-- Wrong -->
<a onclick="doThing()">Click me</a>

An <a> without href isn't a link — it's not keyboard focusable and isn't announced as a link by assistive tech. If it triggers an action instead of navigating, it's a <button>.

5. Forgetting <label> in favor of placeholder#

<!-- Wrong — placeholder disappears once typing starts, low contrast -->
<input placeholder="Email" />
 
<!-- Right -->
<label for="email">Email</label>
<input id="email" type="email" />

Covered in depth in Forms & Validation, but it's fundamentally a semantics mistake: placeholder is a hint, not a label.

6. Using <br> for spacing instead of CSS#

<!-- Wrong -->
<p>Line one<br><br><br>Line two</p>
 
<!-- Right — one <br> for an actual line break within content (e.g. a poem, an address); use margin/padding for spacing -->
<p>Line one</p>
<p style="margin-top: 2rem">Line two</p>

Best Practices#

  • Reach for the most specific element first. <nav> over <div class="nav">, <button> over <div onclick>, <time> over a plain <span> for dates.
  • One <main> per page, containing the primary content — not the header, nav, or footer.
  • One <h1> per page that describes the page's purpose; descend headings sequentially without skipping levels.
  • Use landmark elements for page regions: <header>, , , , . They give you free ARIA landmark roles and free "skip navigation" behavior for screen reader users.

Further Resources#

  • MDN — HTML elements reference — the canonical list of every element and what it means.
  • MDN — Document and website structure
  • WHATWG HTML Living Standard — sections — the actual spec definitions for <article>, <section>, <nav>, <aside>.
  • web.dev — HTML5 semantics

>
</section>
</article>
<aside>Related links</aside>
</main>
<footer>...</footer>
</body>
<a href>
<div class="title"><h1>–<h6>
</
section
>
</article>
blockquote
cite
=
"https://example.com/source"
>
<p>Quoted text goes here.</p>
</blockquote>
<nav>
<main>
<aside>
<footer>
  • Validate structure, not just markup. Run the W3C HTML validator periodically — it catches things like duplicate IDs and invalid nesting that don't throw JS errors but silently break assistive tech.
  • Inspect the accessibility tree, not just the DOM. Chrome DevTools → Elements → Accessibility pane shows exactly what a screen reader will announce for any node — this is the fastest way to catch a semantics mistake before a user does.
  • W3C Markup Validation Service — validate any URL or markup snippet.
  • The A11Y Project — semantic HTML