Day 12: HTML Project — Build a Semantic Static Webpage
We’ve covered headings, links, images, lists, tables, forms, multimedia, semantic layout, and accessibility. Now it’s time to wire them together.
Tutorials teach syntax. Projects build muscle memory. You can read every HTML guide in existence, but you won’t truly own the language until you’ve sat down with a blank file and assembled a coherent page from scratch. This is your first portfolio-ready HTML build.
In this post, we’ll construct a complete, accessible, semantic static webpage step-by-step. You’ll apply everything from Days 1–11 into a single, validated file. We’re keeping this strictly HTML-only: no CSS, no JavaScript, no backend. That’s intentional. Clean structure always precedes presentation. By the end, you’ll have a production-ready index.html that passes real-world validation checks and serves as the perfect foundation for the CSS phase.
🎯 Project Acceptance Criteria
Before we write a single line, here’s exactly what “done” looks like. Your final page must:
- Use valid HTML5 boilerplate with semantic layout containers
- Maintain a logical heading hierarchy (
<h1>→<h2>→<h3>) - Include internal navigation and at least one secure external link
- Embed at least one image, one audio/video element, and a working form
- Explicitly connect all inputs to
<label>tags and use a skip link - Pass the W3C Markup Validator with zero errors
- Trigger zero critical violations in axe DevTools
Keep this checklist open. We’ll verify each criterion as we build.
Phase 1: Skeleton & Semantic Layout
Create a new folder named html-project. Inside it, create index.html and paste the standard HTML5 boilerplate.
Implementation:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Semantic Webpage</title>
</head>
<body>
<header>
<h1>Project Portfolio</h1>
<nav>
<a href="#about">About</a> |
<a href="#contact">Contact</a> |
<a href="https://developer.mozilla.org" target="_blank" rel="noopener noreferrer">MDN Reference</a>
</nav>
</header>
<main id="main-content">
<!-- Core content goes here -->
</main>
<footer>
<p>Built as an HTML consolidation project. © 2026</p> </footer>
</body>
</html>
Code language: HTML, XML (xml)
Verification: Save and open in your browser. Open DevTools (F12) → More Tools → Accessibility. Expand the root node. You should see computed roles: banner (header), navigation (nav), main (main), and contentinfo (footer). Confirm only one <main> exists. If it does, Phase 1 is complete.
Phase 2: Content Structure & Media
Now we populate <main>. We’ll use <article> for the primary content, break it into <section> blocks, and add an <aside> for supplementary information.
Implementation: Replace <!-- Core content goes here --> with:
<article id="about">
<h1>Understanding Semantic HTML</h1>
<p>HTML isn't just about rendering text. It's about communicating meaning to browsers, search engines, and assistive technology.</p>
<section>
<h2>Why Structure Matters</h2>
<p>When you use <code><section></code>, <code><article></code>, and <code><header></code> correctly, you create a readable blueprint. Screen readers can jump directly to landmarks. Crawlers understand your hierarchy.</p>
<img src="https://via.placeholder.com/600x200?text=Semantic+Structure+Diagram" alt="Diagram showing HTML5 semantic layout containers" width="600" height="200">
</section>
<section>
<h2>Next Steps in Your Journey</h2>
<p>Once your structure passes validation, you'll layer CSS for presentation. Never rush to styling before the HTML is solid.</p>
<audio controls preload="metadata" src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"></audio>
</section>
</article>
<aside>
<h3>Quick Reference</h3>
<ul>
<li>Validate before styling</li>
<li>Use <code>rem</code> for typography later</li>
<li>Test with keyboard only</li>
</ul>
</aside>
Code language: HTML, XML (xml)
Verification: Refresh. Check the heading hierarchy: <h1> (Portfolio) → <h1> (Article title) → <h2> → <h3>. Notice we have two <h1> tags. In modern HTML5, this is valid if they belong to different sectioning roots, but for cleaner outlines, you can change the article title to <h2>. Open the Network tab → filter by Media → verify the audio file loads metadata only. If the hierarchy flows and media behaves, Phase 2 is complete.
Phase 3: Interactive Elements & Form
We’ll add a contact section with a fully accessible form that submits to a safe testing endpoint. Implementation: Add this below the <aside>, still inside <main>:
<section id="contact">
<h2>Get In Touch</h2>
<form action="https://httpbin.org/post" method="POST">
<fieldset>
<legend>Contact Information</legend>
<label for="name">Full Name</label>
<input type="text" id="name" name="name" required>
<label for="email">Email Address</label>
<input type="email" id="email" name="email" required>
<label for="message">Message</label>
<textarea id="message" name="message" rows="4" required></textarea>
<label>
<input type="checkbox" name="newsletter"> Subscribe to updates
</label>
<button type="submit">Send Message</button>
</fieldset>
</form>
</section>
Code language: HTML, XML (xml)
Add the skip link at the very top of <body>, right after <body> opens:
<a href="#main-content" class="skip-link">Skip to main content</a>
Code language: HTML, XML (xml)
Verification: Save. Press Tab repeatedly. The skip link should appear. Press Enter. Focus jumps straight to <main>. Fill out the form with valid data and click submit. Open DevTools → Network → click the post request → check the Payload tab. Verify name, email, message, and newsletter appear exactly as expected. If the payload matches and the skip link works, Phase 3 is complete.
Phase 4: Accessibility & Validation Polish
We’re not shipping until this passes automated and manual checks.
Implementation:
- Open W3C Markup Validator. Upload your
index.htmlor paste the code. Fix any nesting, missingalt, or unclosed tag errors. - Install the axe DevTools browser extension. Run it on your page. Fix any flagged critical violations (usually missing
alt, contrast, or heading jumps). - Add this temporary
<style>block to<head>to ensure focus visibility during testing:
<style>
:focus-visible { outline: 3px solid #0d6efd; outline-offset: 2px; }
.skip-link { position: absolute; left: -9999px; top: auto; padding: 0.5rem 1rem; background: #000; color: #fff; z-index: 100; } .skip-link:focus { left: 0; }
</style>
Code language: HTML, XML (xml)
- Test the full page using only
Tab,Shift+Tab, andEnter. Verify every interactive element is reachable and logically ordered.
Verification: Zero validator errors. Zero critical axe violations. Clean keyboard flow. If all three pass, your page is officially production-ready. Phase 4 is complete.
Beginner Pitfalls & Quick Fixes
- Div soup: Reaching for
<div>instead of semantic tags → Fix: reference the layout container decision tree from Day 10. - Broken form payloads: Missing
nameorenctype(only needed for file uploads) → Fix: always verify the Network tab payload before assuming submission failed. - Heading jumps:
<h2>directly under<h1>is fine, but<h1>→<h4>breaks the outline → Fix: restructure content, use CSS for sizing later. - Overusing ARIA: Slapping
role/aria-*on native elements → Fix: remove them, verify screen readers still announce correctly. Native HTML wins. - Debug tip: Always validate before styling. CSS hides structural flaws; HTML validation exposes them.
Synthesis & Portfolio Prep
Run through the acceptance criteria one final time. Once it passes, you’re ready to deploy.
How to publish this in 2 minutes:
- Push the
html-project/folder to a new GitHub repository. - Go to Repository Settings → Pages → Select
mainbranch → Save. - Your site is live at
https://yourusername.github.io/html-project/.
Alternatively, drag the entire folder into Netlify Drop. No CLI. No config. Just a live URL.
This single index.html file is now your baseline. Every future static site you build will start here. The next phase isn’t about adding more HTML. It’s about learning how to dress this structure in CSS without breaking its semantic foundation.
Key Takeaways
- Projects consolidate isolated concepts into working, testable systems
- Semantic HTML + accessibility = portfolio-ready, employer-ready markup
- Validation and DevTools are non-negotiable quality gates
- Clean structure always precedes styling: never rush to CSS before the HTML passes audits
- This file is now your reusable template for every future static build
What’s Next
In the next post, we’ll finally transition from structure to presentation: CSS Fundamentals & The Box Model. You’ll learn how to link external stylesheets, target elements reliably, understand the layout math that drives every website, and apply box-sizing to prevent the most frustrating beginner layout bugs.
Preview question: Once your HTML is validated, what’s the first CSS rule you should apply globally before touching individual elements? Jot down your answer. We’ll cover it next.
← Day 11: Accessibility Basics | Day 12 | Day 13: CSS Fundamentals & Box Model →





Leave a Reply