Text and Semantic Elements
Marking up content by meaning: headings, paragraphs and lists, emphasis, quotes and code, and the semantic elements header, nav, main, article, section, aside and footer.
Why meaning matters
Semantic HTML means choosing the HTML element that describes what a piece of content is: a heading, a list, a navigation menu, a quotation. Compare two ways to write the top of Kestrel Energy's portal:
<!-- Only generic boxes -->
<div class="top">
<div class="menu"><div><a href="/">Home</a></div><div><a href="/outages">Outages</a></div></div>
</div>
<div class="title">My account</div>
<!-- Semantic -->
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/outages">Outages</a></li>
</ul>
</nav>
</header>
<h1>My account</h1>
With the right CSS both can look identical. The difference is in what programs can understand:
-
Assistive technology. A screen reader announces
"navigation, list, 2 items" and "heading level 1, My account". Its
users can jump from heading to heading or straight to the
navigation. With only
divs there is nothing to jump to. See Accessibility Basics. - Search engines and other tools use headings and structure to understand a page. Reader modes, translation tools and browser extensions rely on it too.
-
Developers.
<nav>and<h1>say more than<div class="menu">, and many built-in behaviors come for free.
Headings
A heading element is one of
<h1> to <h6>, which give a
title to the section that follows it. The number is the level:
h1 is the title of the page, h2 a main
section, h3 a subsection of that, and so on.
<h1>Help and support</h1>
<h2>Meter readings</h2>
<p>How and when to submit your readings.</p>
<h3>Smart meters</h3>
<p>A smart meter sends its readings automatically.</p>
<h2>Bills and payments</h2>
<p>Understanding your annual statement.</p>
Three rules keep the outline useful:
-
One
h1per page, naming what the page is about. It usually matches the start of the<title>. -
Do not skip levels on the way down: an
h4directly under anh2makes screen reader users wonder what they missed. Going back up (fromh3toh2) is normal. -
Pick the level, then the size. If an
h2looks too big, change itsfont-sizein CSS. And do not turn bold text into a heading just to make it stand out.
Paragraphs, line breaks and whitespace
A <p> is a paragraph. Inside it, HTML
collapses whitespace: any run of spaces, tabs and
newlines in the source becomes a single space, and the browser wraps
lines where they fit. That is why you can indent and break your code
freely.
<p>This text has lots of
spaces and a line break in the source.</p>
<p>Kestrel Energy<br>Customer service<br>Monday to Friday, 08:00–20:00</p>
<pre>
Meter Reading Date
E-4402 12345 2026-09-30
G-1187 3021 2026-09-30
</pre>
-
<br>forces a line break where the break is part of the content, such as in an address or a poem. Do not use a stack of<br>s for spacing; that is a job for CSS margins. -
<pre>(preformatted text) keeps every space and newline and uses a monospace font: right for command output and text art, wrong for normal prose. -
<hr>marks a thematic break between paragraphs, such as a change of topic.
Lists
HTML has three kinds of list:
<ul>
<li>Find your meter cupboard</li>
<li>Note the numbers before the decimal point
<ul>
<li>Electricity: day and night register</li>
<li>Gas: one register</li>
</ul>
</li>
<li>Take a photo as proof</li>
</ul>
<ol>
<li>Log in to the portal</li>
<li>Choose <strong>Meter readings</strong></li>
<li>Enter the numbers and press <strong>Submit</strong></li>
</ol>
<dl>
<dt>kWh</dt>
<dd>Kilowatt-hour, the unit of electricity use.</dd>
<dt>m³</dt>
<dd>Cubic meter, the unit of gas use.</dd>
</dl>
-
<ul>(unordered list): the order does not matter. Shown with bullets by default. -
<ol>(ordered list): the order matters, as in steps. Numbered by default; the attributesstart="4",reversedandtype="a"change the numbering. -
<dl>(description list): pairs of a term (<dt>) and its description (<dd>), such as a glossary or a set of properties.
The only children a <ul> or
<ol> may have are
<li> elements. A nested list therefore goes
inside an <li>, as in the example.
Navigation menus are usually a <ul> of links,
because a menu is a list of choices; CSS removes the bullets and
puts the items side by side.
Emphasis, quotes and code
Within a paragraph, a set of small elements marks words and phrases by meaning:
<p><strong>Warning:</strong> never open the meter cupboard if you <em>smell</em> gas.</p>
<p>The <abbr title="distribution system operator">DSO</abbr> owns the meter.
Readings are due by <time datetime="2026-11-05">5 November</time>.</p>
<p>Press <kbd>Ctrl</kbd> + <kbd>F5</kbd> to reload, or run <code>ipconfig /flushdns</code>.</p>
<p>Gas used: 1,240 m<sup>3</sup>, about 2.2 tonnes of CO<sub>2</sub>.</p>
<p><mark>New:</mark> pay your annual bill in monthly installments.</p>
<blockquote>
<p>Switching took five minutes, and the first bill was right.</p>
</blockquote>
<p>From the <cite>Kestrel Customer Survey 2026</cite>.</p>
| Element | Meaning |
|---|---|
strong |
Strong importance, seriousness or urgency |
em |
Stress emphasis: the stressed word that changes the meaning of the sentence ("if you smell gas", not if you see it) |
b, i |
Bold or italic text without extra importance:
b for keywords or product names,
i for technical terms, foreign phrases or a
thought
|
mark |
Highlighted for relevance, like a highlighter pen |
small |
Side comments and fine print |
abbr |
An abbreviation; the title can give the full
form
|
time |
A date or time, with a machine-readable
datetime value
|
code, kbd, samp
|
Computer code, keyboard input, program output |
sub, sup |
Subscript and superscript |
blockquote, q |
A quotation from another source: a block of its own, or a short one inside a sentence (the browser adds the quote marks) |
cite |
The title of a work: a book, report, film or survey |
For a block of code, combine two elements:
<pre><code>…</code></pre>.
pre keeps the line breaks, code says it is
code. Remember to escape < and &
inside it with
character references; this whole encyclopedia does exactly that.
Block-level and inline
Elements fall into two broad groups by the way they take up space.
Block-level content is
content whose elements start on a new line and stretch across the
full available width, stacking from top to bottom: paragraphs,
headings, lists, div, blockquote,
pre, and the page regions below.
Inline content is content that
flows along within a line of text and wraps with it: text itself,
links, strong, em, span,
code, images.
<div>A div is a block.</div>
<p>A paragraph is a block, with <span>a span</span>, <a href="#">a link</a>
and <strong>strong text</strong> flowing inside it.</p>
<div>Another block, again on its own line.</div>
div, p {
outline: 2px solid steelblue;
margin: 0.75rem 0;
}
span, a, strong {
outline: 2px dashed darkorange;
}
The solid outlines are blocks: each is as wide as the frame, however short its text. The dashed ones are inline: only as wide as their content, sitting in the line. Making the result frame narrower would make the paragraph's lines wrap, with the inline boxes wrapping along.
Strictly, the HTML standard no longer uses the words "block" and
"inline". It sorts elements into
content categories: flow content (almost
everything that can appear in the body) and
phrasing content (the text-level part of it, which may go
inside a paragraph). How an element is drawn comes from the CSS
display property, and the browser's default stylesheet
gives p display: block and
span display: inline. You can change that
in CSS without changing the meaning; see
The Box Model.
The regions of a page
A sectioning element is
one of the elements that divide a page into its major regions:
header, nav, main,
article, section, aside and
footer. (In the standard's own vocabulary, only
article, section, nav and
aside are "sectioning content"; the other three are
usually grouped with them.) They were introduced with HTML5 and
replaced countless <div id="header">s.
| Element | Use it for |
|---|---|
header |
Introductory content: the site logo and name at the top, or the heading and date at the start of an article |
nav |
A block of major navigation links: the main menu, a table of contents, breadcrumbs. Not every group of links |
main |
The main content of the page, without the repeated header,
menu and footer. Only one visible main per page
|
article |
A self-contained piece that would make sense on its own: a news item, a blog post, a product card, a comment |
section |
A thematic part of a page or article, normally with its own heading |
aside |
Content only loosely related to what surrounds it: a sidebar, a tip box, related links |
footer |
Closing information: copyright, contact details, legal links; for a page or for an article |
Here is a small page built from them. The CSS only draws a labeled border around each region, to make the structure visible:
<header>
<p>Kestrel Energy</p>
<nav><a href="#">Home</a> · <a href="#">Outages</a> · <a href="#">My account</a></nav>
</header>
<main>
<article>
<h1>Planned maintenance</h1>
<p>Gas supply in Harbor Street is interrupted on 12 October from 09:00 to 13:00.</p>
</article>
<aside>
<p>Questions? Call 0800 123 4567.</p>
</aside>
</main>
<footer>
<p>© 2026 Kestrel Energy</p>
</footer>
body { font-family: system-ui, sans-serif; }
h1 { font-size: 1.25rem; margin: 0.25rem 0; }
p { margin: 0.25rem 0; }
header, nav, main, article, aside, footer {
border: 1px solid gray;
padding: 0.25rem 0.5rem;
margin: 0.4rem 0;
}
header::before, nav::before, main::before,
article::before, aside::before, footer::before {
display: block;
font: 12px monospace;
color: dimgray;
}
header::before { content: "header"; }
nav::before { content: "nav"; }
main::before { content: "main"; }
article::before { content: "article"; }
aside::before { content: "aside"; }
footer::before { content: "footer"; }
article or section?
Ask whether the piece would still make sense if it were lifted out
and shown somewhere else, for example in a feed. If yes, it is an
article (each outage report on the outage page). If it
is a part of something larger that only makes sense in place, such
as the "Payment options" part of a billing page, it is a
section. If you only need a box to style, it is
neither: use a div.
A few more structural elements
-
<search>wraps a search or filter form. It is newer than the others: Baseline widely available since April 2026. -
<address>holds contact information for the page or article, not just any postal address. -
<figure>with<figcaption>groups an image, diagram or code listing with its caption; see Links, Images and Media.
Screen readers expose header, nav,
main, aside, footer and
search as landmarks that users can jump between (with
conditions: a header or footer inside an
article, for example, is not a page landmark). How that
works is part of
Accessibility Basics.
div and span: no meaning on purpose
The div element is a generic block-level container with no meaning of its own. The span element is its inline counterpart: a generic wrapper around a piece of text. Both exist so that you can group or style content when no semantic element fits:
<div class="notice">
<p>Your bill for September is <span class="amount">€84.20</span>.</p>
</div>
.notice {
border-left: 4px solid steelblue;
padding: 0.25rem 1rem;
font-family: system-ui, sans-serif;
}
.amount {
font-weight: bold;
white-space: nowrap;
}
The div exists only to draw the border; the
span only to keep the amount bold and on one line.
Neither tells a screen reader anything, and that is fine: the
meaning is already carried by the paragraph. The rule of thumb is to
look for a meaningful element first and fall back on
div or span when there is none. Layout
wrappers for flexbox and grid are a typical, legitimate use.
Microdata: meaning for machines
Semantic elements describe the role of content (a heading, an article), but not what it is about. To tell a search engine "this is an organization, this is its phone number", HTML has microdata: three attributes that label content with terms from a shared vocabulary, usually schema.org.
<div itemscope itemtype="https://schema.org/Organization">
<p><span itemprop="name">Kestrel Energy</span>,
customer service <span itemprop="telephone">0800 123 4567</span></p>
</div>
itemscope (a boolean attribute) starts an item,
itemtype says what kind of thing it is, and each
itemprop names one property. Nothing changes on screen.
Search engines can use such structured data for rich results, such
as opening hours or ratings next to a link. The same information can
also be given as a separate JSON-LD script block in the head, which
keeps it out of the visible markup; that is the format Google's
documentation generally recommends. More about what search engines
use is in
Metadata, Sharing and Search Basics.