Semantic Page Layout
Over the last lessons you met each semantic element on its own: header, nav, main, section, article, aside, footer, address, details, and dialog. Now it is time to put them together into a real page.
A good page layout is like a well-planned building: a clear entrance, signs on every floor, one main hall, and a place for the small rooms on the side. Visitors, search engines, and assistive technology can all find their way around, because the structure is in the markup, not only in the paint.
What You Will Learnβ
- The standard semantic page skeleton
- Where each element goes, and which one is a landmark
- A skip link, and a sensible heading outline
- Laying the page out with CSS grid, without breaking the order
- Reading order, tab order, and responsive behaviour
- A practical checklist to test any page
The Skeletonβ
Almost every content page can start from this shape:
- HTML Code
- Browser Output
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sourdough for Beginners | The Bread Bin</title>
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>
<header>
<a href="/" class="logo">The Bread Bin</a>
<nav aria-label="Main">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/recipes">Recipes</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main id="main" tabindex="-1">
<article>
<header>
<h1>Sourdough for Beginners</h1>
<p>By Asha Rao Β· <time datetime="2026-10-17">17 October 2026</time></p>
</header>
<section aria-labelledby="starter">
<h2 id="starter">Make a starter</h2>
<p>Mix flour and water, then wait.</p>
</section>
<section aria-labelledby="bake">
<h2 id="bake">Bake the loaf</h2>
<p>Heat the oven, and score the dough.</p>
</section>
</article>
<aside aria-labelledby="tools-title">
<h2 id="tools-title">Tools you need</h2>
<ul>
<li>A kitchen scale</li>
<li>A Dutch oven</li>
</ul>
</aside>
</main>
<footer>
<p><small>Β© 2026 The Bread Bin</small></p>
<nav aria-label="Footer">
<a href="/privacy">Privacy</a>
<a href="/contact">Contact</a>
</nav>
</footer>
</body>
</html>
Sourdough for Beginners
By Asha Rao Β·
Make a starter
Mix flour and water, then wait.
Bake the loaf
Heat the oven, and score the dough.
The demo shows the layout inside this lesson's page, so it uses h2 and h3 here. In a real page, the article title is the single h1, as in the code.
Read the skeleton from top to bottom:
| Part | Role | Notes |
|---|---|---|
| Skip link | None | The first focusable item, jumping to main |
Page header | banner | Logo, site name, and often the main nav |
nav | navigation | Named with aria-label, because there are two on the page |
main | main | One per page, with the page's unique content |
article | Generic (article) | A self-contained piece, with its own header |
section | region only when named | Each has a heading |
aside | complementary | Related, not essential |
Page footer | contentinfo | Copyright, legal and contact links |
Two header elements appear above. The first is the page header (a banner). The second sits inside an article, so it is only the article's own heading group. See Header for the full rules.
Try It: Build the Page Frameβ
Switch the parts on and off, and see which landmarks a screen reader user would get.
- HTML Code
- Browser Output
<header>β¦</header> <!-- banner -->
<nav aria-label="Main">β¦</nav> <!-- navigation -->
<main>β¦</main> <!-- main -->
<aside>β¦</aside> <!-- complementary -->
<footer>β¦</footer> <!-- contentinfo -->
// List the page's landmarks, like a screen reader would
const selectors = "header, nav, main, aside, footer, [role]";
document.querySelectorAll(selectors).forEach((element) => {
console.log(element.tagName.toLowerCase(), element.getAttribute("role") || "(implicit)");
});
article, sectionsβ¦
A screen reader's landmark list: banner (header), navigation (nav), main (main), complementary (aside), contentinfo (footer)
The Skip Linkβ
Keyboard users have to tab through your whole menu on every page before they reach the content. A skip link is the shortcut. It is the first focusable element, and it jumps to main.
<a class="skip-link" href="#main">Skip to main content</a>
β¦
<main id="main" tabindex="-1">
.skip-link {
position: absolute;
inset-inline-start: 0.5rem;
top: -4rem; /* off screen until focused */
background: #1d4ed8;
color: #fff;
padding: 0.5rem 1rem;
z-index: 10;
}
.skip-link:focus {
top: 0.5rem; /* slides into view */
}
Do not use display: none on a skip link, because then nobody can focus it. The tabindex="-1" on main lets the browser move the focus into the content after the jump. See Main for details.
Heading Outlineβ
Headings form the table of contents that screen reader users navigate by. Plan them as a simple outline:
h1 Sourdough for Beginners β one per page
h2 Make a starter
h2 Bake the loaf
h3 Scoring the dough
h2 Tools you need β the aside
- One
h1that names the page (usually matching thetitle). - Do not skip levels (an
h2followed by anh4). - Choose levels by importance, not by the size you want. Use CSS to change the size.
- Every
sectionhas a heading, and theasidehas one too. - The "document outline algorithm" is not implemented by browsers, so nesting
sectionelements does not change heading levels. See Section.
Laying It Out with CSS Gridβ
The elements are just boxes. CSS decides where they sit. A common layout is a header on top, content and a sidebar in the middle, and a footer at the bottom:
- HTML Code
- Browser Output
body {
min-height: 100vh;
margin: 0;
display: grid;
grid-template-rows: auto 1fr auto; /* header, content, footer */
}
main {
display: grid;
grid-template-columns: minmax(0, 1fr) 16rem; /* article, aside */
gap: 2rem;
padding: 1rem;
max-width: 70rem;
margin-inline: auto;
}
/* One column on small screens */
@media (max-width: 48rem) {
main {
grid-template-columns: 1fr;
}
}
Resize the window: on narrow screens, the aside drops below the article.
Keep the Source Order Meaningfulβ
CSS can move boxes around, but screen readers and the Tab key follow the HTML order, not the visual order. Watch out for:
order,grid-areaplacement, orflex-direction: row-reversethat makes the visual order differ from the DOM order. Keyboard focus then seems to jump around.- A sidebar placed before
mainin the HTML, so every visitor reads it first. Putasideafter the article it relates to, and let the layout position it. - Content that only makes sense in a certain visual position ("see the box on the right"). Describe it by name instead: "see the tools list".
The rule: write the HTML in the order you want it read, and use CSS only to arrange it.
Common Layout Patternsβ
| Layout | Structure |
|---|---|
| Blog post | Header, nav, main with one article, an optional aside, footer |
| Landing page | Header, nav, main with several named section elements (hero, features, pricing), footer |
| Dashboard | Header, nav (sidebar menu), main with sections and a dialog for settings, no footer needed |
| Docs site | Header, nav (docs menu), main with article, aside with the page's table of contents, footer |
| Web app | A stable shell (header, nav, main, footer), with only main's content changing, and focus moved on route change |
In all of them, the same shell repeats on every page, so people learn it once.
Page Quality Beyond Landmarksβ
A semantic page is more than tags:
langon thehtmlelement, andlangon foreign phrases.- A unique, descriptive
titleper page. It is the first thing a screen reader announces. - A viewport meta tag, so mobile browsers do not zoom out.
- A visible focus style on every link and button.
- Sufficient colour contrast, and a layout that works at 200% zoom.
- Real links and buttons, as explained in Why Semantic HTML.
- Landmark labels only where you need to tell similar ones apart.
Accessibility at a Glanceβ
- Use native landmarks (
header,nav,main,aside,footer). Do not repeat their roles in ARIA. - Exactly one visible
main. - Name repeated landmarks (two
navelements, twoasideelements). - Add a skip link, and make it visible on focus.
- Keep the DOM order logical, and match the visual order.
- Do not hide the page's structure from assistive technology with
aria-hiddenon a landmark. - Test by keyboard, by landmark list in a screen reader, and with CSS turned off.
Security and Privacy Notesβ
- Layout is not protection. Hiding an admin
sectionor afooterlink with CSS does not hide it from the page source. Enforce permissions on the server. - Do not put personal data in landmark labels or headings (for example "Account 4821 overview") where it can appear in tab titles, history, and screen shares.
- Escape any user-supplied text you place in headings,
title, oraria-label. - Third-party widgets (ads, comments, embeds) inside
asideoriframeshould be clearly titled and restricted withsandboxandrelvalues such asnoopener, so they cannot change your page or capture its focus.
Global Audience Notesβ
- Set
langanddironhtml, and use logical CSS properties (margin-inline,padding-inline-start,inset-inline-start), so the whole layout mirrors in right-to-left languages. - Allow text to grow, since translations can be 30% longer or more. Avoid fixed-height headers and buttons.
- Keep the page light. Many visitors use slow or metered connections, and old phones. Semantic HTML is small and fast by nature.
- Use plain words in landmark labels ("Main", "Footer"), and translate them with the page.
- Do not rely on hover or wide screens. Test at narrow widths and on touch.
Common Mistakes to Avoidβ
- A page built only from
divelements (div soup). - More than one visible
main, or none. - Page-level
headerandfooterplaced insidemain. - Two unnamed
navelements. - Skipping the skip link, or hiding it with
display: none. - Several
h1elements, or skipped heading levels. - A
sectionwith no heading, used as a styling wrapper. - Putting the sidebar before the content in the HTML.
- Reordering with CSS so keyboard focus jumps around.
- Adding
role="main"tomain, or other redundant ARIA. - Forgetting
langand a usefultitle. - Never testing with the keyboard, a screen reader, or CSS turned off.
Practice Timeβ
Try these in your editor:
- Build the skeleton from this lesson, and open it with CSS turned off.
- Add a skip link, and test it with the Tab key.
- Name two
navelements, and check the names in the accessibility panel. - Lay the page out with CSS grid: header, content and aside, footer.
- Make the aside fall below the article on narrow screens.
- Put the
asidefirst in the HTML, then move it after the article. Tab through each version. - Add a heading to every
section, and write the outline on paper. - Replace a
div-only page of your own with semantic elements. - List the page's landmarks with a screen reader, or a browser extension.
- Bonus: run the checklist below against one of your own pages, and fix every item you miss.
Try It: The Page Layout Checklistβ
Use this checklist on any page you build.
Quick Recapβ
Click a question to check your answer.
1. What are the main parts of a semantic page layout?
A page header (banner), nav (navigation), one main, optional aside (complementary), and a page footer (contentinfo), plus article and section elements inside main to organise the content.
2. Why add a skip link?
It lets keyboard and screen reader users jump past the repeated menu straight to the main content, saving many key presses on every page. It must be the first focusable element and visible when focused.
3. Does CSS change the order screen readers and the Tab key follow?
No. They follow the HTML source order. Write the HTML in the reading order you want, and use CSS only to arrange the boxes. Avoid reordering that makes the visual and DOM orders differ.
4. When must a nav or aside be given a name?
When there is more than one of the same landmark on the page, so users can tell them apart in a landmark list. Use aria-label or aria-labelledby.
5. How should headings be arranged on a page?
One h1 for the page, then h2 for main sections and h3 below them, with no skipped levels. Choose levels by meaning and use CSS for size.
6. How do you test a layout?
Use the keyboard alone, list the landmarks and headings with a screen reader or browser tool, turn CSS off to check the source order, and zoom to 200% and a narrow width.
Key Takeawaysβ
- A semantic page is a skeleton of landmarks: header, nav, main, aside, footer, with
articleandsectioninsidemain. - Use one visible
main, a skip link, and named repeated landmarks. - Plan the heading outline first: one
h1, no skipped levels, and a heading for everysection. - Use CSS grid for the layout, but keep the HTML order meaningful, because assistive technology and the keyboard follow it.
- Do not add ARIA roles that native elements already provide.
- Layout hides nothing from the page source, so enforce permissions on the server.
- Use logical CSS properties, set
langanddir, and test on narrow, slow, and right-to-left setups. - Always test with the keyboard, a screen reader, and CSS turned off.
Congratulations, you have finished the Semantic HTML section. Return to the Semantic HTML overview to review the elements, or revisit Why Semantic HTML to see how far you have come.