HTML Structure and Semantics
Table of Contents
Every web page has structure — headings, paragraphs, navigation, sidebars, footers. HTML gives you elements that describe what content is, not just how it looks. Using the right elements makes your pages accessible to screen readers, understandable to search engines, and easier for other developers to maintain.
This tutorial builds on HTML Hello World and covers how to structure a complete page with semantic HTML5 elements.
The Document Structure
Every HTML page follows this skeleton:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<!-- Your content goes here -->
</body>
</html>
<!DOCTYPE html>— tells the browser this is HTML5<html lang="en">— the root element;langhelps screen readers pronounce content correctly<head>— metadata (not visible on the page): title, character set, viewport settings, CSS links<body>— everything the user sees
Semantic Elements
HTML5 introduced elements that describe the purpose of content, replacing the old pattern of <div class="header"> everywhere:
<body>
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
</header>
<main>
<article>
<h2>Article Title</h2>
<p>Article content...</p>
</article>
<aside>
<h3>Related Links</h3>
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2026 My Website</p>
</footer>
</body>
What each element means
| Element | Purpose |
|---|---|
<header> |
Introductory content or navigation for its parent section |
<nav> |
Major navigation links |
<main> |
The primary content of the page (only one per page) |
<article> |
Self-contained content that could stand alone (blog post, news story, comment) |
<section> |
A thematic grouping of content with a heading |
<aside> |
Content tangentially related to the main content (sidebars, pull quotes) |
<footer> |
Footer for its parent section (copyright, links, contact info) |
Why semantics matter
- Accessibility — Screen readers use semantic elements to navigate. A blind user can jump directly to
<main>or list all<nav>elements on a page. - SEO — Search engines understand your content structure better with semantic markup.
- Maintainability —
<nav>is immediately clear;<div class="nav-wrapper">requires reading the class name.
Headings
Headings create a document outline. Use them hierarchically — don’t skip levels:
<h1>Page Title</h1> <!-- One per page (usually) -->
<h2>Major Section</h2>
<p>Content...</p>
<h3>Subsection</h3>
<p>Content...</p>
<h3>Another Subsection</h3>
<p>Content...</p>
<h2>Another Major Section</h2>
<p>Content...</p>
<h3> should always be a subsection of an <h2>, regardless of how big you want the text.
Text Content
Paragraphs and line breaks
<p>This is a paragraph. Browsers add space above and below paragraphs automatically.</p>
<p>This is another paragraph. Use <br> for a line break within a paragraph,
but only when the break is meaningful (like in a poem or address).</p>
Emphasis and importance
<p>This is <em>emphasized</em> text (usually italic).</p>
<p>This is <strong>important</strong> text (usually bold).</p>
Use <em> and <strong> instead of <i> and <b> — they convey meaning, not just styling.
Lists
<!-- Unordered list (bullet points) -->
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
<!-- Ordered list (numbered) -->
<ol>
<li>Step one</li>
<li>Step two</li>
<li>Step three</li>
</ol>
<!-- Description list (term + definition pairs) -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language — the structure of web pages</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets — the presentation of web pages</dd>
</dl>
Blockquotes and code
<blockquote cite="https://example.com/source">
<p>The best way to predict the future is to invent it.</p>
<footer>— Alan Kay</footer>
</blockquote>
<!-- Inline code -->
<p>Use the <code>querySelector()</code> method to find elements.</p>
<!-- Code block -->
<pre><code>function hello() {
console.log("Hello, world!");
}</code></pre>
Links
<!-- External link -->
<a href="https://developer.mozilla.org">MDN Web Docs</a>
<!-- Open in new tab (add rel for security) -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">External Site</a>
<!-- Internal link -->
<a href="/about">About Us</a>
<!-- Link to section on same page -->
<a href="#contact">Jump to Contact</a>
<!-- Email link -->
<a href="mailto:hello@example.com">Email us</a>
Images
<!-- Always include alt text -->
<img src="/images/photo.jpg" alt="A golden retriever playing in a park" width="800" height="600">
<!-- Decorative images get empty alt -->
<img src="/images/divider.svg" alt="" role="presentation">
<!-- Figure with caption -->
<figure>
<img src="/images/chart.png" alt="Bar chart showing monthly revenue growth from January to June 2026">
<figcaption>Monthly revenue growth, Jan–Jun 2026</figcaption>
</figure>
The alt attribute is critical for accessibility. Describe what the image shows, not what it is (“A chart showing revenue growth” not “chart.png”).
Tables
Use tables for tabular data — never for layout:
<table>
<caption>Quarterly Sales Results</caption>
<thead>
<tr>
<th scope="col">Quarter</th>
<th scope="col">Revenue</th>
<th scope="col">Growth</th>
</tr>
</thead>
<tbody>
<tr>
<td>Q1 2026</td>
<td>$1.2M</td>
<td>+15%</td>
</tr>
<tr>
<td>Q2 2026</td>
<td>$1.4M</td>
<td>+17%</td>
</tr>
</tbody>
</table>
<thead>, <tbody>, <th>, and scope attributes help screen readers understand the table structure.
Forms (Preview)
Forms deserve their own tutorial, but here’s the basic structure:
<form action="/submit" method="POST">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<button type="submit">Submit</button>
</form>
Key rules:
- Every input needs a
<label>with a matchingfor/idpair - Use the right
typeattribute (email,tel,number,url) — it enables validation and mobile keyboards - Use
requiredfor mandatory fields
Putting It All Together
Here’s a complete blog post page with proper semantics:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Understanding CSS Grid - My Blog</title>
</head>
<body>
<header>
<nav aria-label="Main navigation">
<a href="/">Home</a>
<a href="/blog">Blog</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<article>
<header>
<h1>Understanding CSS Grid</h1>
<time datetime="2026-05-18">May 18, 2026</time>
</header>
<section>
<h2>What is CSS Grid?</h2>
<p>CSS Grid is a two-dimensional layout system...</p>
</section>
<section>
<h2>Basic Usage</h2>
<p>To create a grid, set display: grid on the container...</p>
<pre><code>.container { display: grid; }</code></pre>
</section>
</article>
<aside aria-label="Related articles">
<h2>Related Posts</h2>
<ul>
<li><a href="/blog/flexbox">CSS Flexbox Guide</a></li>
<li><a href="/blog/responsive">Responsive Design</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2026 My Blog. All rights reserved.</p>
</footer>
</body>
</html>
Common Mistakes
- Using
<div>for everything — If a semantic element fits, use it - Multiple
<h1>tags — Use one per page for the main title - Skipping heading levels — Don’t jump from
<h2>to<h4> - Missing
alton images — Every<img>needsalt(empty string for decorative images) - Using
<br>for spacing — Use CSS margin/padding instead - Tables for layout — Tables are for data only
What’s Next
Now that you understand page structure, you can style it with CSS. Start with the CSS Box Model to understand how elements take up space, then move to Flexbox and Grid for layout.