Clean Semantic HTML for Page Templates
Nested div elements with class names like header and footer render fine but tell browsers and assistive technology nothing about the page. A handful of semantic elements and a tidy heading outline fix most of that.
From div soup to structure
Older templates often build the entire page from div elements, telling them apart only by class names such as header, sidebar or footer. The page looks right, but to a browser, a search crawler or a screen reader those are anonymous boxes. Developers call this pattern div soup.
Here is a typical example:
<div id="wrapper">
<div class="header">
<div class="logo">Site Name</div>
<div class="nav">
<a href="/">Home</a>
<a href="/about/">About</a>
</div>
</div>
<div class="content">
<div class="main-text">
<h1>Page heading</h1>
<p>Body text.</p>
</div>
<div class="sidebar">
<p>Related links</p>
</div>
</div>
<div class="footer">
<p>Footer text</p>
</div>
</div>
The same layout with semantic elements reads almost like an outline:
<header>
<a href="/" class="logo">Site Name</a>
<nav aria-label="Main">
<a href="/">Home</a>
<a href="/about/">About</a>
</nav>
</header>
<main>
<article>
<h1>Page heading</h1>
<p>Body text.</p>
</article>
<aside>
<h2>Related links</h2>
</aside>
</main>
<footer>
<p>Footer text</p>
</footer>
Fewer wrappers, no guessing about roles, and selectors in the stylesheet become simpler because they can target the elements themselves.
The layout elements and what they mean
header
A header holds introductory content for whatever contains it. Placed directly in the body, it is the site banner: logo, site name, primary navigation, maybe a search form. Inside an article or section, it holds that block's title and details such as a date or author.
nav
Use nav for major blocks of navigation: the main menu, a table of contents, pagination, breadcrumbs. Not every group of links needs one. A short list of legal links in the footer can live without it, though wrapping it in a labeled nav does no harm.
main
The main element wraps the content that is unique to the page, leaving out repeated site furniture such as the header, footer and global sidebars. A document should have only one visible main, and it should not sit inside header, nav, footer, article or aside.
article
An article is a self contained piece that would still make sense on its own: a blog post, a news story, a comment, a product card. A useful test is whether you could syndicate it elsewhere without the surrounding page. An article can have its own header and footer.
aside
An aside contains material related to the surrounding content but not part of its main flow. Related links, a pull quote, a glossary note or an author bio all fit. On wide screens it often becomes a sidebar, but the element describes the relationship, not the position.
footer
A footer closes its section. At the body level it carries the copyright line, contact details and policy links. Inside an article it might hold tags, categories or a credit.
A clear heading outline
Headings give the page a tree that both sighted readers and assistive technology use. In most templates, each page gets one h1 naming its main topic. Sections beneath it use h2, subsections h3, and so on.
<main>
<h1>Planning a portfolio site</h1>
<section>
<h2>Choosing a layout</h2>
<p>Single page or several pages.</p>
<h3>Navigation patterns</h3>
<p>Menus, anchors and breadcrumbs.</p>
</section>
</main>
Many screen reader users move through a page by jumping from heading to heading, so skipping from h2 straight to h4 leaves a gap in that tree. Pick heading levels for structure, then size them with CSS. If a heading should look smaller, change its font-size rather than choosing a lower level.
Landmarks without extra attributes
Semantic elements create landmarks automatically. A header at the top level of the body becomes the banner landmark, nav becomes navigation, main becomes main, aside becomes complementary, and a top level footer becomes contentinfo. Screen reader users can list these landmarks and jump between them.
Because the mapping is built in, adding role="main" to a main element or role="navigation" to a nav is redundant. When a page has more than one nav, give each a label so they can be told apart:
<nav aria-label="Main">
<a href="/work/">Work</a>
<a href="/about/">About</a>
</nav>
<nav aria-label="Footer">
<a href="/privacy/">Privacy</a>
<a href="/terms/">Terms</a>
</nav>
Mistakes to look for when converting a template
Most templates can be cleaned up in an hour or two, and the same problems turn up again and again.
The first is headings used for looks. A template might put the site name in an h1 on every page, then use h4 for card titles because that size happened to fit the design. The fix is to decide the outline first and size everything with classes afterward. The page's own topic gets the h1, and the site name becomes a link or a paragraph.
The second is clickable elements that are not links or buttons. A div with a click handler cannot be reached with the Tab key and is not announced as interactive. If it goes somewhere, make it an a with an href. If it does something on the page, such as opening a menu, make it a button.
The third is lists that are not marked up as lists. Menus, card collections and feature rows are all lists of similar items. Wrapping them in ul and li lets screen readers announce how many items there are, which helps people decide whether to explore or skip.
The fourth is missing text alternatives. Icons used as the only content of a link need an accessible name, either visually hidden text or an aria-label on the link. Decorative images need an empty alt so they are skipped.
None of these changes alters how the page looks, which makes them safe to do before any visual customization begins.
A complete page skeleton
Put together, a clean template page needs surprisingly little markup:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Building semantic layouts</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<a href="/" class="logo">Site Name</a>
<nav aria-label="Main">
<ul>
<li><a href="/articles/">Articles</a></li>
<li><a href="/about/">About</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header>
<h1>Building semantic layouts</h1>
<p>Published <time datetime="2026-03-30">March 30, 2026</time></p>
</header>
<p>Opening paragraph of the article.</p>
<section>
<h2>Why the elements matter</h2>
<p>Supporting detail.</p>
</section>
</article>
<aside>
<h2>Related reading</h2>
<ul>
<li><a href="/css-grid/">Page layout with CSS Grid</a></li>
</ul>
</aside>
</main>
<footer>
<p>Site Name</p>
<nav aria-label="Footer">
<a href="/privacy/">Privacy</a>
</nav>
</footer>
</body>
</html>
The time element gives the date a machine readable value while showing a friendly one. The lang attribute tells screen readers which pronunciation rules to use.
None of this markup fixes the visual layout. CSS Grid on main can place the article and aside side by side on wide screens and stack them on phones, and the HTML stays exactly the same either way. That separation is the real payoff: structure in the markup, presentation in the stylesheet, and a template that is easier to restyle, maintain and use with any device.
Frequently asked questions
Can a page have more than one header element?
Yes. A page usually has one site header, and each article or section can have its own header for its title and metadata. Only the site header acts as the banner landmark.
Should every div be replaced with a semantic element?
No. A div is still the right choice for grouping things purely for styling or layout. Use semantic elements when the content has a meaning that one of them describes.
Why should a page have only one main element?
The main element marks the content that is unique to that page. Screen readers offer a shortcut to jump straight to it, which only works if there is one clear target. The HTML standard allows a single visible main per document.
Do semantic elements replace CSS classes?
No. Elements describe what content is, and classes handle how specific components look. Most templates use both.