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
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.
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> 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 of
Use
<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.
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.
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).
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.
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>
<!-- 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>...).
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>.
<!-- 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>
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.
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.