HTML Text Elements
Most of a web page is text, and most of the markup you write will be choosing which element a piece of text belongs in. There is a reliable way to make that choice and a tempting way to get it wrong.
The tempting way is to pick by appearance: this line should be big, so h1; this should be bold, so b. The reliable way is to pick by meaning: this line is the title of the page, so h1; this word carries a warning, so strong. The two often produce the same element, which is why the wrong method survives. When they differ, the appearance-led choice is the one that breaks.
Headings are an outline
h1 through h6 are not six sizes. They are six levels, and together they form the page's outline - the same outline a screen reader user navigates by, and a search engine summarises from.
<h1>HTML Text Elements</h1>
<p>One page, one main heading.</p>
<h2>Headings</h2>
<p>A section of the page.</p>
<h3>Choosing a level</h3>
<p>A subsection of that section.</p>
<h2>Paragraphs</h2>
<p>Back up a level, because this is a sibling of Headings.</p>
Open this example in the editor and change it. Nothing you type is saved.
Two rules follow from treating them as an outline:
One h1 per page, naming what the whole page is about. More than one and there is no single answer to "what is this page?"
Do not skip levels. Jumping from h2 to h4 describes a subsection of a section that does not exist. If the h4 looks right and the h3 looks wrong, that is a CSS problem with a CSS solution.
A screen reader can list every heading on a page and jump between them, which for most users is how they find out what a page contains. A page with one heading, or with six h1 elements, gives them a table of contents with one entry or six equally important ones.
Paragraphs, line breaks and thematic breaks
p is a paragraph. It is the default container for running text and you will use it more than anything else.
br forces a line break inside a block of text where the break is part of the content - a postal address, a line of a poem, a verse. It is not a way to add space between paragraphs; that is a margin, and margins belong in CSS.
hr represents a thematic break: a change of subject within a section. It renders as a line by default, which makes it tempting as a decoration. Use it when the break is in the content, and CSS borders when the line is decoration.
<p>
Omni Academy<br>
14 Example Street<br>
Doha
</p>
<hr>
<p>A new subject begins here.</p>
Open this example in the editor and change it. Nothing you type is saved.
Emphasis and importance
Four elements are involved and they divide into two pairs.
strong means this is important. em means this word carries the stress, in the way that saying a word differently changes a sentence's meaning.
b and i are the ones that were once "bold" and "italic" and now have narrower jobs: b draws attention without implying importance (a keyword, a product name in a review), and i marks an alternate voice or mood - a technical term, a phrase in another language, a thought.
<p><strong>Warning:</strong> this operation cannot be undone.</p>
<p>I said <em>she</em> wrote it, not that I did.</p>
<p>The <i lang="la">Felis catus</i> is the domestic cat.</p>
Open this example in the editor and change it. Nothing you type is saved.
The difference is audible. A screen reader can change its delivery for strong and em. It has nothing to say about b and i, which is correct - they are not carrying importance.
If what you actually want is bold text with no extra meaning, the honest answer is a class and a CSS rule.
The rest of the text semantics
A handful of smaller elements cover cases that come up often enough to be worth knowing.
<p>Water is H<sub>2</sub>O, and 2<sup>3</sup> is 8.</p>
<p>Price: <del>50</del> <ins>35</ins> today only.</p>
<p>Search results for <mark>semantic markup</mark> are highlighted.</p>
<p><small>Terms and conditions apply.</small></p>
Open this example in the editor and change it. Nothing you type is saved.
sub and sup are subscript and superscript, for formulae and footnote markers. del and ins mark removed and added content, which matters on anything with a revision history - a screen reader announces them, where a strikethrough drawn in CSS is silent. mark highlights text for the reader's current purpose, most obviously a search term. small is for side comments and small print.
Quotations and code
<p>As the specification puts it:</p>
<blockquote cite="https://html.spec.whatwg.org/">
<p>Authors must not use elements, attributes, or attribute values for purposes other than their appropriate intended semantic purpose.</p>
</blockquote>
<p>She called it <q>a markup language, not a programming language</q>.</p>
<p>Use <code><p></code> for a paragraph.</p>
<pre><code>function greet(name) {
return "Hello, " + name;
}</code></pre>
Open this example in the editor and change it. Nothing you type is saved.
blockquote is a quotation that stands as its own block; q is a short one inside a sentence, and the browser supplies the quotation marks, in the right style for the document language. code marks a fragment of code inline. pre preserves whitespace exactly as written, which is why a code block is conventionally pre wrapping code: one preserves the layout, the other says what the text is.
Note <p> in that example. To show a tag on screen rather than have it interpreted, the angle brackets have to be written as entities. There is a whole lesson on that later.
The ones people forget
A few more elements each solve a specific problem well, and each is routinely replaced by a span and a class that does less.
<p>Published <time datetime="2026-03-14">14 March 2026</time>.</p>
<p>The <abbr title="World Wide Web Consortium">W3C</abbr> publishes specifications.</p>
<p>Press <kbd>Ctrl</kbd> + <kbd>S</kbd> to save.</p>
<p>The program printed <samp>File not found</samp>.</p>
<p>Solve for <var>x</var> in the equation above.</p>
<p>A <dfn>void element</dfn> is one that cannot have content.</p>
<p>From <cite>The Art of Readable Markup</cite>, page 14.</p>
<address>
Written by <a href="mailto:lena@example.com">Lena</a>.
</address>
Open this example in the editor and change it. Nothing you type is saved.
time carries a machine-readable date in datetime alongside whatever wording you prefer for humans - so "last Tuesday" can still be indexed correctly. abbr gives an abbreviation its expansion. kbd is keys the reader should press, samp is output a program produced, and var is a variable in a mathematical or programming sense. dfn marks the point in the text where a term is being defined, which is what lets a glossary link back to it. cite names a work, not a person. address gives contact details for the nearest article or for the page as a whole, and is for contact information rather than for any postal address that happens to appear in the text.
None of these change much visually. All of them tell something downstream what the text is, which a span cannot.
Practice task
Take a page you have already written and audit its text. For every piece of styled text, ask what it is rather than how it looks. Replace any bolding that means "important" with strong, any italics that mean "stressed" with em, and check that your headings form an outline you could read aloud as a table of contents. Then open the page in the browser and use the developer tools accessibility panel to list the headings - what it shows you is what a screen reader user gets.