Part 2: Semantic HTML — Headings, text content, section elements
Introduction
When I first started writing HTML, I used <div> for everything. Navigation? <div>. Article content? <div>. Page footer? <div>. It worked visually — browsers rendered it — but the page was structurally meaningless. Screen readers had no idea what was navigation versus main content. Search engines had no signal about what text mattered most. CSS ended up full of context-dependent class names just to compensate for the lack of structure.
Semantic HTML solves this. Using elements that describe what content is, not just how it looks, makes pages accessible, maintainable, and honestly easier to write CSS for.
What "Semantic" Means
A semantic element clearly describes its meaning to both the browser and the developer. Compare:
<!-- Non-semantic -->
<div class="nav-container">
<div class="nav-item"><a href="/">Home</a></div>
</div>
<!-- Semantic -->
<nav>
<a href="/">Home</a>
</nav>Both render identically by default. The difference is in what the markup communicates:
The browser knows
<nav>is navigation — it can be listed by accessibility toolsSearch engines understand
<nav>is navigational, not primary contentOther developers reading the code understand the intent immediately
Headings
Headings create the document outline. The browser, screen readers, and search engines all use heading levels to understand document hierarchy.
Rules I Follow
One <h1> per page. It identifies the primary topic of the page. On a blog post, it is the post title. On a dashboard, it is the dashboard name.
Do not skip levels. If you have a <h2>, the next level down should be <h3>, not <h5>. Skipped levels confuse the document outline and trip up screen readers.
Do not use headings for visual size. If you want large bold text that is not a heading, use CSS. Do not use <h2> just because it looks the right size.
Text Content Elements
Paragraphs
<p> is for prose — sentences and paragraphs. Do not use it for single labels or non-prose text.
Strong and Emphasis
<strong>— serious importance, urgency, or warning. Screen readers may emphasise this.<em>— stress emphasis, i.e., spoken emphasis that would change meaning. Screen readers may inflect this.
These are semantic elements. For purely visual bold/italic without semantic meaning:
Code
<code>— inline code, filenames, command names<pre>— preserves whitespace and line breaks, for code blocks<pre><code>together — the correct pattern for multi-line code blocks
Quotations
Abbreviations
The title attribute provides the expansion on hover/screen reader.
Lists
Unordered List
Use when the order does not matter (feature lists, navigation items, bullet points).
Ordered List
Use when sequence matters (installation steps, ranked items, table of contents).
Description List
<dl> (description list) is the correct element for glossaries, metadata pairs, or term–definition structures. I use it in documentation pages where I'm presenting key-value pairs.
Nesting Lists
Structural Sectioning Elements
HTML5 introduced elements that describe the role of sections in the page layout.
<header>
<header>Contains introductory content for a page or section: logos, site titles, navigation, search. There can be a <header> inside <article> or <section> as well — each represents the introductory content for that element.
<nav>
<nav>For major navigation blocks. Not every group of links needs to be <nav> — reserve it for the primary and secondary navigation menus.
<main>
<main>There should be exactly one <main> per page. It identifies the primary content, distinct from headers, footers, and sidebars. Screen readers use it to skip directly to content.
<article>
<article>Self-contained content that makes sense on its own and could be syndicated independently: blog posts, news articles, forum posts, documentation pages.
<section>
<section>A thematic grouping of content. Usually has a heading. Use <section> when grouping related content under a heading; use <div> when grouping purely for styling with no semantic meaning.
<aside>
<aside>Content tangentially related to the primary content: sidebars, pull quotes, related links, advert zones.
<footer>
<footer>Footer content for a page or section: copyright, links, contact information.
<div> and <span>
<div> and <span><div> and <span> are non-semantic containers. Use them when no semantic element fits the purpose.
The rule: reach for a semantic element first. Use <div> or <span> only when nothing semantic applies.
Page Structure Example
A typical documentation page combining the elements above:
Summary
<h1>–<h6>
Document outline and section headings
<p>
Prose paragraphs
<strong> / <em>
Semantic importance / emphasis
<b> / <i>
Visual bold / italic without semantic meaning
<code> / <pre>
Inline code / code blocks
<ul> / <ol> / <dl>
Unordered / ordered / description lists
<header>
Introductory content for page or section
<nav>
Primary navigation blocks
<main>
Primary page content (one per page)
<article>
Self-contained, independently distributable content
<section>
Thematic grouping with a heading
<aside>
Tangentially related content
<footer>
Footer for page or section
<div> / <span>
Non-semantic containers for styling/scripting
Up Next
Part 3 covers links, images, and media — the elements that connect pages and embed content.
Last updated