Semantic HTML · 1 / 8
lesson 1

What "semantic" means in practice

Pick the right tag, and a whole second audience starts understanding your page — screen readers, search crawlers, browser extensions.

~ 14 min read·lesson 1 of 8
0 / 8

You can build a button out of a <div>. It will look like a button. It will even click like a button if you wire up a JavaScript handler. But a screen reader will not call it a button, the keyboard will not focus it, and a Chinese-language search crawler will skim past it. The page works for sighted mouse users — and only them.

That gap is what semantic HTML fixes. The word semantic just means "carries meaning". A semantic tag tells every reader of the page — humans, browsers, assistive tech, search engines — what each chunk is, not just how it should look.

The accessibility tree

When the browser parses your HTML, it does not just build the visible page. It also builds a parallel structure called the accessibility tree — a stripped-down version of your document that lists every element along with its role ("button", "link", "heading"), its name ("Sign up", "About this site"), and any state ("expanded", "checked").

Screen readers, voice control, and browser extensions all read from this tree. They do not look at pixels. They look at roles and names.

DOM accessibility tree<button>Buy</button><h1>Pricing</h1><a href="/x">More</a>button "Buy"heading 1 "Pricing"link "More"
The DOM is the visible markup; the accessibility tree is the labelled version assistive tech actually reads.

A <button> becomes the entry "button, name: Buy". A <div> styled like a button becomes the entry "generic" — no role, no name, invisible to anyone navigating by buttons. Same pixels, completely different document.

Default roles, no ARIA needed

Every native HTML element comes with a default role. A <nav> has the role navigation. A <main> has the role main. A <button> has button. You do not have to write anything extra — the role ships with the tag.

You may have heard of ARIA (Accessible Rich Internet Applications) — a set of attributes you sprinkle on tags to add or change roles. ARIA exists for one reason: to patch the gap when no native element fits. Treat it as a last resort.

two-buttons.html
<!-- Native: role, focus, keyboard, screen reader — all free. -->
<button type="button">Save</button>

<!-- DIY: you have to recreate every one of those by hand. -->
<div role="button" tabindex="0" onclick="...">Save</div>

The two lines above look identical on screen. The first is a real button: it focuses when you tab, fires on Space and Enter, announces as "button" in screen readers, and respects the user's "force-click sensitivity" preferences. The second focuses only because you set tabindex="0", fires only on click (not Enter, not Space), and is a real-world maintenance problem.

The rule of thumb is the first rule of ARIA: don't use ARIA. If a native element does the job, use it.

check your understanding
You build a clickable card for a product using <div onclick="..."> with no other attributes. A keyboard-only user lands on your page. What can they do with the card?

What changes for real users

Picking the right semantic tag is not abstract politeness — it changes what real people can do with your page. A short, concrete tour of who notices and how.

Screen-reader users can jump between landmarks (main, nav, aside) with a keyboard shortcut. If you wrap your menu in a <nav>, a blind user can skip past it in one keystroke. Wrap it in a <div>, and they have to listen to every link.

Keyboard-only users rely on default focus behaviour. A <button> focuses when they tab; a fake button skips them. A heading list (<h1><h3>) gives a "headings menu" they can navigate; a wall of styled <div>s doesn't.

Search engines lean on headings, landmarks, and <article> to figure out what your page is about. A page where every section header is a <div class="title"> is harder to index well.

Reader-mode users (the "show me just the article" button in browsers) get a clean view because reader mode looks for <article> and <main>. Pages built from generic divs often render as blank in reader mode.

Future you maintaining the code. <nav>, <main>, and <aside> tell the next person what each section is. <div class="wrapper-2"> does not.

Tip

In Chrome DevTools, open the Elements panel and click the "Accessibility" sub-tab. It shows you the same tree screen readers see. If your custom button shows "generic" instead of "button" there, you have a problem.

A useful picture: HTML is a building, and semantic tags are the room signs. With signs, anyone — sighted or not, on a phone or a screen reader — can find the kitchen. Without signs, only people who can see the shape of the room (the visible page) can navigate. Semantic HTML is the signage layer.

check your understanding
Two pages render identically. Page A uses <nav>, <main>, and <article>. Page B uses <div class="..."> for everything. Which statement is most accurate?
check your understanding
You write <div role="button" tabindex="0" onclick="save()">Save</div>. A screen-reader user finds it. What is still broken compared to a real <button>?
check your understanding
A teammate says, "let's just add aria-label="navigation" to this div instead of changing it to a nav." What is the strongest argument against?
next lesson →
KeepLearningcertificate
for completing
Semantic HTML
0 of 8 read