HTML Reference · CLN v2.2 · Feb 2026
HTML: Semantics
= structure that carries meaning — not just visual layout ! div soup costs you SEO, accessibility, and maintainability # #html #semantics #a11y #seo #structure
Semantic HTML = the right element for the right job. The browser, search engines, and assistive technologies all read your tag choices. Hover operators for menus · click spoilers to test yourself.

01/Why SemanticsFoundation
// ##why · The cost of div soup
=semantic tag = element whose name describes its role in the document
=<div> and <span> are non-semantic — they carry zero meaning
Benefits of semantic HTML
+SEO — search engines understand content structure
+Accessibility — screen readers use landmarks to navigate
+Maintainability — code intent is self-documenting
+Default styles — browser applies sane defaults (h1 bold, em italic)
+Focus management — interactive elements are keyboard-accessible by default
Cost of div soup
-screen reader can't identify page regions — user must read everything
-Google can't distinguish heading from paragraph
-<div onclick> is not keyboard-focusable — Tab skips it
-no implied ARIA roles — must add them manually
→extra work to replicate what semantic HTML provides for free
?What ARIA role does <nav> implicitly carry? role="navigation". Every semantic element maps to an implicit ARIA role. Using the element is always preferred over adding the role manually — <nav> beats <div role="navigation"> every time.

02/Document Structure — Landmark ElementsReference
// ##landmarks · One page, one main
.<header> — introductory content for its parent (page or section)
*can appear multiple times — once per <article>, <section>, page
!inside <header> → ARIA role = banner only when it's a direct child of <body>
.<nav> — major navigation links · ARIA: navigation landmark
*use for primary / secondary nav — not every group of links
.multiple <nav> → add aria-label to distinguish them for screen readers
.<main> — primary content · ARIA: main landmark
!only one <main> per page — screen readers jump directly to it
!never nest <main> inside <header>, <footer>, or <aside>
.<aside> — tangentially related content · ARIA: complementary
*sidebars, pull quotes, callout boxes, related links
.<footer> — closing content for its parent
*ARIA: contentinfo — only when direct child of <body>
<body> <header> ← banner (ARIA) <nav> ← navigation landmark <main> ← main landmark · only one! <article> <header> ← article header (not banner) <section> <aside> ← complementary <footer> ← contentinfo (ARIA)

03/Content ElementsReference
Sectioning
=<article> — self-contained, independently distributable content
*blog post, news item, forum post, product card, tweet
*test: could it stand alone syndicated in RSS? → <article>
=<section> — thematic grouping within a document
!should always have a heading — if it doesn't need one, use <div>
=<figure> + <figcaption> — self-contained media with caption
*images, code blocks, diagrams, charts — anything with a caption
Text content
=<p> — paragraph · block-level
!don't use for spacing — use CSS margin
=<blockquote> — extended quotation
.cite="URL" — machine-readable source (not displayed)
=<ul> / <ol> — unordered / ordered lists
!only direct child of <ul>/<ol> is <li> — no divs between them
=<dl> / <dt> / <dd> — description list
*glossaries, metadata pairs (key: value), FAQs
=<time datetime=""> — machine-readable date/time
*datetime="2026-02-23" · datetime="2026-02-23T14:30"
?When should you use <dl> instead of a table? When data is key-value pairs without tabular relationships. A product spec sheet (Weight: 1.2kg, Color: Black, SKU: XY-001) is semantically a description list, not a table. Tables imply rows and columns with headers — dl/dt/dd implies term-definition pairs.

04/Inline Semantic ElementsReference
Emphasis & Importance
=<strong> — strong importance · renders bold by default
~visual bold vs semantic importance Use <strong> when the content is genuinely important — screen readers may stress it. Use CSS font-weight:bold for purely visual bold with no semantic weight. <b> = stylistic bold without importance.
=<em> — stress emphasis · renders italic by default
*"I never said that" — changes meaning, not just style
=<mark> — highlighted / relevant text
*search results highlighting matched terms
=<small> — fine print, legal, side comments
Technical & References
=<code> — inline code fragment
=<pre> — preformatted text, preserves whitespace
*wrap <code> inside <pre> for code blocks
=<kbd> — keyboard input: Ctrl+S
=<abbr title=""> — abbreviation with expansion
*<abbr title="HyperText Markup Language">HTML</abbr>
=<cite> — title of a work (book, article, film)
!<cite> is for works, not people — Moby Dick not Herman Melville
=<q> — inline quotation · auto-adds quotation marks
=<del> / <ins> — deleted / inserted text (with dates via datetime)
=<sup> / <sub> — superscript / subscript

05/article vs section — The Most Confused PairGotcha
~tension: both group content — but the relationship to the document is different
<article> — standalone
=self-contained — makes sense without surrounding context
+test: could it appear in an RSS feed independently? → yes → article
.use for: blog post, news article, product card, comment, tweet embed
.can nest: <article> inside <article> = related item
*blog post containing comments: each comment = nested <article>
→implicit: this content could leave this page and still mean something
<section> — part of a whole
=thematic grouping — only meaningful in context of its document
!rule: if it has no heading, use <div> instead
.use for: chapters, tabbed content areas, "About" / "Contact" zones
.contributes to document outline — creates implicit heading level
→implicit: this is part of the page — removes context = meaningless
?A product listing page with 12 product cards. Which element wraps each card? <article>. Each product card is independently meaningful — it could appear in a search result, price comparison site, or RSS feed. The container holding all cards might be <section> (if it has a heading like "Featured Products") or <main>.
?A single-page landing site with sections: Hero, Features, Pricing, Contact. Which element? <section> for each — they are thematic parts of one document. None makes sense in isolation. Each should have a heading (even visually hidden with sr-only class if needed for a11y).

06/Heading HierarchySEO · a11y
// ##headings · h1–h6 rules
=headings create the document outline — not visual size
!one <h1> per page — the page title · screen readers navigate by headings
!never skip levels: h1 → h3 (no h2) is an outline gap
→screen reader user who navigates by headings hits a structural hole
!don't choose heading level for visual size — use CSS for that
*want a big h3? h3 { font-size: 2rem } — don't use h1 for its size
.h2 = major sections · h3 = subsections of h2 · h4–h6 = rare deep nesting
+correct heading structure = automatic table of contents for screen readers
h1 Page Title h2 Major Section A h3 Subsection A.1 h3 Subsection A.2 h2 Major Section B h3 Subsection B.1 h4 Deep detail (use sparingly) ✕ bad: h1 Page Title h3 Subsection ← skipped h2! h2 Section (after h3) ← out of order!
?A page has a site logo (h1), then articles each with their own h1. What's wrong? Multiple h1s create an ambiguous document outline. Search engines and screen readers can't determine the primary topic. Fix: logo = <p> or <span> with CSS styling, article titles = <h2> within the page context. If articles are in <article> elements they may have their own h1 per spec, but in practice one h1 per page is safer for SEO.

07/When <div> is the Right AnswerDecision Rule
// ##div-rules · div is not wrong — it's misused
=<div> = generic block container · <span> = generic inline container
=correct use: layout wrapper with no semantic meaning
.use <div> when:
+you need a CSS/JS hook with no semantic role (flex container, grid wrapper)
+grouping elements for styling only — no document meaning
+JS mount point for a component
+the section has no heading and no semantic role
.use <span> when:
+targeting a word or phrase for CSS / JS with no semantic meaning
→decision rule: if a semantic element fits — use it. If nothing fits — div/span is correct, not a compromise
?Quick decision: <div> or <section> for a sidebar with related articles? <aside> — it's tangentially related content. Not <section> (no thematic grouping), not <div> (it has semantic meaning). If it has a heading like "Related Articles", <aside> with an <h2> inside is the correct pattern.