Lesson 03 · Part 1 · Foundations

Semantic HTML

"Semantic" means "carrying meaning". Semantic HTML uses elements that say what a thing is: a heading, a button, a list. Browsers and screen readers use that meaning. You get a lot of accessibility for free.

In one minute

In plain words

Imagine a bookshop where every box looks the same and has no label. You could still find a book, but only by opening every box. Semantic HTML puts labels on the boxes: "Menu", "Main content", "Heading", "Button". A screen reader reads the labels, so its user can go straight to the right box.

1. The problem: a school portal made of divs

Arjun is blind and uses a screen reader. He opens his school portal to submit homework. The page looks normal, but it is div soup.

Div soup

Bad
<div class="top">Green Valley School</div>
<div class="title">My homework</div>
<div class="item">Physics worksheet</div>
<div class="btn" onclick="send()">
  Submit homework
</div>
"No headings." "No landmarks." (Tab skips "Submit homework" completely.)

Semantic

Fixed
<header>Green Valley School</header>
<main>
  <h1>My homework</h1>
  <ul><li>Physics worksheet</li></ul>
  <button type="button">Submit homework</button>
</main>
"main landmark" "heading level 1, My homework" "list, 1 item" "Submit homework, button"

With div soup, Arjun cannot jump to the content. He must listen to the whole page, line by line. Then he cannot press the submit "button" at all. He misses the deadline.

Check
  1. Which single change in the fixed code lets Arjun submit with the keyboard? (Answer: <div class="btn"> became <button>.)

2. What meaningful elements give you for free

A landmark is a big region of the page, like "navigation" or "main". Screen reader users can list landmarks and jump between them. Most screen readers also let users jump from heading to heading (for example, the H key in NVDA and JAWS).

ElementAnnounced asWhat you get for free
<header>bannerA landmark for the site's top area. Only when it is not inside main, article, section, aside or nav.
<nav>navigationA landmark for a group of main links.
<main>mainA landmark for the page's main content. Use one per page.
<article>articleA complete piece that makes sense alone: a post, a product card.
<section>region (only if it has a name)Groups related content. It becomes a landmark only when labelled, for example with aria-labelledby.
<aside>complementaryA landmark for side content, like "Related books".
<footer>content infoA landmark for the page's bottom area, when not inside another section.
<h1>–<h6>heading, level 1–6An outline of the page. Users jump by headings.
<ul>, <ol>list, 3 itemsThe item count, so users know how long the list is.
<table>table, 5 rows, 4 columnsMoving cell by cell, with row and column headers read out.
<button>buttonFocus with Tab. Works with Enter and Space.
<a href>linkFocus with Tab. Works with Enter. Can open in a new tab.
<form> + <label>edit text, "Email"The label becomes the field's name. Clicking the label focuses the field.

Step 1. Tick each fix to rebuild the portal. The panels scan the real HTML each time.

Fixes to apply

Step 2. Press Tab into the demo page. Count the stops.

Show the HTML of the demo page

          

Landmarks list

Headings list

Lists

Tab stops

Try it yourself
  1. Tick only "Real headings". How many headings appear? Do any landmarks appear? Why not?

3. Role, name and state

Assistive tech asks three questions about every control. What is it? What is it called? What condition is it in?

WordQuestionExample on a food-delivery app
RoleWhat kind of thing is it?button, link, checkbox, heading
NameWhat is it called?"Place order" (from the button's text)
StateWhat condition is it in?checked, not checked, expanded, collapsed, pressed

Here is how a screen reader might combine them. The exact words differ between screen readers.

"Place order, button"
"Extra cheese, checkbox, not checked"
"Delivery options, button, collapsed"

Native elements fill in role, name and state for you. A <div> fills in none of them. You can add them with ARIA (later lessons), but the first rule of ARIA is: use the real element if one exists.

Check
  1. For <input type="checkbox" checked> Veg only, name the role, name and state. (checkbox, "Veg only", checked.)

4. Fake button vs real button

A real <button> is focusable and works with Enter and Space. A div with a click handler only works with a mouse. Adding tabindex="0" makes the div focusable, but the keys still do nothing.

Step 1. Use only the keyboard. Press Tab to reach each "Add to basket", then press Enter and Space.

Step 2. Watch the counters. Then try the mouse for comparison.

A. <div onclick>

Add to basket

Mouse: 0 · Keyboard: 0

B. <div tabindex="0" onclick>

Add to basket

Mouse: 0 · Keyboard: 0

C. <button>

Mouse: 0 · Keyboard: 0

Tab to a control to hear it.
Try it yourself
  1. Get the keyboard count of C to 2, using Enter once and Space once. Can you get A's keyboard count above 0?

5. Looks are not meaning

CSS decides how something looks. HTML decides what it is. A screen reader ignores size and boldness.

Looks like a heading

Bad
Today's specials
<div class="big-bold">Today's specials</div>
"Today's specials" (plain text; missing from the headings list)

Is a heading, styled small

Fixed

Today's specials

<h2 class="small-caps">Today's specials</h2>
"heading level 2, Today's specials"

Pick the element for its meaning. Then use CSS to make it look the way you want.

When div and span are fine

Check
  1. A designer wants a small grey line of text above the main title. Is it a heading? (Usually not. Use <p> and style it.)

6. Pick the right element

Six pieces of a real page. Choose the element that carries the right meaning.

Quiz. Choose one answer per line. You can change your answer.

    Common mistakes

    You seeWhy it is a problemFix
    <div onclick> as a buttonNo focus, no role, no Enter or Space.<button type="button">
    Big bold div as a titleMissing from the headings list.<h1>–<h6>, styled with CSS
    Picking h4 because it is "the right size"The level tells structure, not size.Pick the level by structure. Resize with CSS.
    Menu links in plain divsNo landmark, no item count.<nav> with <ul>
    Two or more <main> elements shown at onceUsers cannot tell which is the real content.One visible <main> per page.
    <div role="button" tabindex="0">You must write all the key handling yourself.Use <button>.
    Try it yourself
    1. Right-click a page you use and choose "Inspect". Count the divs. Find one that should be a button, nav or heading.
    2. In your browser's developer tools, open the Accessibility panel. Click a button and read its role and name.
    3. In lab 1, tick the fixes one at a time. Which fix adds the most to the screen reader's lists?

    Remember