8. Semantic layout

Structure that means something

So far you have marked up the content of a page: headings, paragraphs, lists, images, links and forms. Now we look at how to mark up the structure - the layout that wraps that content.

For a long time, pages were laid out with <div> elements and class names like class="header" or class="footer". A <div> carries no meaning - it is just a box. Semantic elements are boxes that also say what they are. That meaning helps screen readers describe the page, helps search engines understand it, and makes your code easier for other developers to read.

These are better than <div> for structure because they give the structure meaning, which helps screen readers announce each part correctly and makes your intent clear.

A semantic page skeleton

This is the same layout you could build with <div>s, but every part now says what it is:

A screen reader can now announce "banner", "navigation", "main" and "content info" as it moves through the page, instead of just "group" after "group".

Key points

Exercises

Exercise 1 - Build a semantic page skeleton

Preparation: re-read "Structure that means something" and the skeleton example above.

Create a new page with a <header> (containing a heading and a <nav>), a <main> (containing one <section> with a heading and a paragraph), and a <footer>. Use no <div> elements.

Try it in: save as a new .html file and open in a browser, or use CodePen / VS Code. Starter: <header>…</header><main>…</main><footer>…</footer>
Hint 1 - direction

Start with the three outer parts: header, main, footer.

Hint 2 - partial solution

The heading and <nav> go inside <header>; the <section> goes inside <main>.

Hint 3 - full solution

Check your work: you used <header>, <nav>, <main>, <section> and <footer>, and no <div>.

Exercise 2 - Article or section for a blog post?

Preparation: re-read the key point about <article> versus <section>.

You are marking up a blog page that shows one full blog post, followed by its comments. Decide which element wraps the post itself and which wraps the comments list, then write both. Explain your choice in one sentence.

Try it in: your editor - nothing needs to look different in the browser; this is about meaning.
Hint 1 - direction

One of them "makes sense on its own"; the other is a group of related items.

Hint 2 - partial solution

The post is self-contained content, so it is an <article>.

Hint 3 - full solution

Wrap the post in <article> and the comments in a <section>. A post makes sense by itself (you could share it alone), while comments are a themed group that only means something attached to the post.

Check your work: post → <article>; comments → <section>.

Exercise 3 - Predict how <main> helps

Preparation: re-read the point about <main> in the theory section.

Without running anything, predict: what does a screen-reader user gain when a page uses <main> correctly? Give one concrete benefit.

No code needed - answer in a sentence, then compare with Hint 3.
Hint 1 - direction

Think about what the user wants to skip past.

Hint 2 - partial solution

<main> marks where the page's unique content starts.

Hint 3 - full solution

A screen reader can jump straight to <main>, skipping the repeated navigation and header text, and land directly on the actual content of the page. This is also what a "skip to main content" link targets.

Check your work: you mentioned finding or reaching the main content more quickly, not just "it is tidier code".

Exercise 4 - Fix a page that uses <div> everywhere

Preparation: re-read the list of semantic elements above.

The page below uses <div> with class names instead of semantic elements. Rewrite it using <header>, <nav>, <main>, <article> and <footer>.

Try it in: your editor - the page should look the same, but the markup should now describe its meaning.
Hint 1 - direction

Match each class name to the element that means the same thing.

Hint 2 - partial solution

class="header" → <header>; class="nav" → <nav>; class="content" → <main>.

Hint 3 - full solution

Check your work: you replaced every structural <div> with the matching semantic element, and class="post" became <article>.