Skip to content

Refactoring a Page to Semantic HTML

The best way to cement what you have learned is to take a real page, see what is wrong with it, and fix it deliberately. This lesson walks through a complete refactor.

Here is a working but poorly structured HTML page. It renders correctly in a browser, but the structure communicates nothing:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Trail Blog</title>
</head>
<body>
<div id="top">
<div id="site-name">Trail Blog</div>
<div id="links">
<a href="/">Home</a>
<a href="/about.html">About</a>
</div>
</div>
<div id="content">
<div class="post">
<div class="post-head">Choosing Your First Trail</div>
<div class="post-date">May 2025</div>
<div class="post-body">
<div>For a first outing, stay under 5 miles.</div>
<div class="tip">Tip: Check trail reports before you go.</div>
<div>Look for easy-rated trails on local hiking sites.</div>
</div>
</div>
</div>
<div id="bottom">
<div>© 2025 Trail Blog</div>
<div><a href="mailto:hello@trailblog.com">Contact</a></div>
</div>
</body>
</html>
IssueDescription
<div id="top">Should be <header>
<div id="site-name">Should be <h1>
<div id="links">Should be <nav>
<div id="content">Should be <main>
<div class="post">Should be <article>
<div class="post-head">Should be <h2>
<div class="post-date">Should be <p>
<div class="post-body">Unnecessary wrapper — remove it
Content <div>s inside post-bodyShould be <p> elements
<div class="tip">Should be <aside>
<div id="bottom">Should be <footer>
Footer content <div>sShould be <p> elements
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Trail Blog</title>
</head>
<body>
<header>
<h1>Trail Blog</h1>
<nav>
<a href="/">Home</a>
<a href="/about.html">About</a>
</nav>
</header>
<main>
<article>
<h2>Choosing Your First Trail</h2>
<p>May 2025</p>
<p>For a first outing, stay under 5 miles.</p>
<aside>
<p><strong>Tip:</strong> Check trail reports before you go.</p>
</aside>
<p>Look for easy-rated trails on local hiking sites.</p>
</article>
</main>
<footer>
<p>© 2025 Trail Blog</p>
<p><a href="mailto:hello@trailblog.com">Contact</a></p>
</footer>
</body>
</html>
  • <div id="top"><header> — The top of every page is not just visually the top; it is the introductory landmark.
  • <div id="site-name"><h1> — Site names are headings. One <h1> per page.
  • <div id="links"><nav> — This is major site navigation.
  • <div id="content"><main> — Primary content deserves the <main> landmark.
  • <div class="post"><article> — A blog post is self-contained and independently meaningful.
  • <div class="post-head"><h2> — Article titles are headings. Using a <div> styled to look like a heading is meaningless to screen readers and search engines.
  • <div class="tip"><aside> — The tip is related but secondary — exactly what <aside> is for.
  • <div id="bottom"><footer> — The bottom of the page is the footer landmark.
  • All remaining content <div>s → <p> — Text content belongs in paragraphs, not anonymous boxes.

Open index.html in VS Code.

By now your file should already have <header>, <main>, <footer>, <section>, <aside>, and <nav> in place from the previous lessons. Do a final review pass:

  1. Check every <div> in the file. If you have any left, ask yourself: does a semantic element fit here? If yes, replace it.
  2. Check heading hierarchy. Your <h1> should be inside <header>. Your <h2> headings should be inside <main>. No levels should be skipped.
  3. Check your <section> elements. Each one should have its own <h2> (or deeper heading).
  4. Check <aside>. Is it inside a <section> and related to that section’s content?
  5. Check <nav>. Is it inside <header> and linking to real pages?

When you are done, index.html should have a structure something like this:

<body>
<header>
<h1>Your Topic</h1>
<nav>
<a href="index.html">Home</a>
<a href="about.html">About</a>
</nav>
</header>
<main>
<section>
<h2>First Subtopic</h2>
<p>...</p>
<aside><p><strong>Tip:</strong> ...</p></aside>
</section>
<section>
<h2>Second Subtopic</h2>
<p>...</p>
<img src="images/photo.jpg" alt="...">
</section>
</main>
<footer>
<p>Built while learning HTML.</p>
<p><a href="mailto:you@example.com">Contact</a></p>
</footer>
</body>

Save, open in your browser, and confirm everything still renders correctly. It should look identical to before — structure is invisible until CSS gets involved.

  • Semantic HTML communicates meaning, not just appearance.
  • <div> is a generic container — use it only when no semantic element fits.
  • Page-level structure: <header><main><footer>.
  • Content organization inside <main>: <section> (related group), <article> (standalone content), <aside> (supplementary).
  • <nav> marks major navigation blocks as a landmark.
  • Proper heading hierarchy (<h1><h2><h3>) must be maintained within this structure.