"Headings aren't text sizes. They're the page's outline — the table of contents the browser builds for free."
Headings: – Are Hierarchy, Not Sizes
Are Hierarchy, Not Sizes
The biggest beginner mistake with headings is picking them by visual size: "I want this big, so I'll use <h1>; I want this small, so I'll use <h4>." That logic ships a broken page. Headings are the page's outline — what a screen reader reads when the user asks to hear all headings, what a search engine extracts as document structure, what determines whether "jump to next heading" actually works.
Rules:
- Exactly one
<h1>per page (the primary title — usually inside<main>). - Don't skip levels.
<h2>follows<h1>;<h3>follows<h2>; you don't jump<h1>→<h4>just because the font looks right. - Style separately. If you want an
<h2>that looks small, that's CSS's job:h2.subtle { font-size: 1rem; }. The element's level is semantic; the visual size is style.
Paragraphs Are Not <br> Soup
Every body of running text goes in a <p>. <br> is for hard line breaks inside a paragraph where the break is part of the content (poetry, addresses, song lyrics). It is not the right tool for spacing between paragraphs. Two paragraphs is two <p> elements. Three lines of <br> is what destroyed the readability of 90s GeoCities pages.
Lists: Three Kinds, Each With A Job
<ul>— unordered list. The order doesn't matter (shopping list, navigation links, feature bullets). 90% of lists on the web.<ol>— ordered list. The order matters (recipe steps, ranking, sequence). Renumbering by moving items is automatic.<dl>— description list. Term/definition pairs (glossary, metadata, key-value display). Each pair is<dt>(term) +<dd>(description).
Don't fake lists with <br>-separated text or <div>s holding bullet characters. Real list elements make the screen reader announce "list with five items" before reading them, which is what gives blind users the same overview sighted users get from glancing at bullets.
Quotes
<blockquote cite="url"> for block-level quoted passages. <q> for inline quotes (the browser auto-adds quotation marks, language-appropriate). <cite> for the title of a referenced work (a book, film, paper) — not for the author's name. The cite attribute on <blockquote> takes a URL pointing to the source.
Inline Semantics: Don't Reach For <span> First
HTML has rich inline semantic elements. Most beginners reach for <span class="foo"> when there's a perfectly good semantic element:
<em>— stress emphasis. Screen readers read with vocal stress.<strong>— strong importance. Different from emphasis (importance, not stress).<mark>— highlighted text (search result match, reviewer annotation). Visible default: yellow background.<time datetime="2026-05-25">— machine-readable dates and times.<abbr title="HyperText Markup Language">HTML</abbr>— abbreviation with the full term in the tooltip.<code>— inline code or technical terms. Pair with<pre>for code blocks.<kbd>— keyboard input (<kbd>Cmd</kbd>+<kbd>C</kbd>).
<b> and <i> still exist, but they're semantic-light. Use <strong> for importance, <em> for stress, <mark> for highlight. <b> is reserved for stylistic offset without semantic weight (a product name); <i> for an alternate voice (technical term in another language). 99% of the time you want <strong> or <em>.Pippa's Note
<em> for vocal stress, <strong> for the important parts, <code> for tech terms, <blockquote> for the opening epigraph. When Dad's VoiceOver reads a lesson aloud, the stress lands in the right places without any extra ARIA tagging.