Semantic HTML: The *defaults* are already good
Before you write CSS, write HTML. well
What does "semantic" mean
Use the label that describes the purpose, not the appearance:
<nav>for navigation, not<div class="nav">.<main>for main content.<article>for standalone content (a post, a product listing).<aside>for related but separable content.<header>/<footer>for headers and footers (both of the site and of an<article>).<section>for topic groupings with title.<button>for actions,<a>for navigation. Never the other way around.
Immediate benefits
Free accessibility. Screen readers understand structure without ARIA. Keyboard users navigate by landmarks.
SEO is better. Engines understand hierarchy.
Simpler CSS. article > header > h1 is a useful selector. If everything is <div>, you need classes for everything.
Less classes. Pico CSS, classless, shows that with semantic HTML you are already 80% of the way done.
Practical examples
A list of posts:
<ol class="post-list" reversed>
<li>
<article>
<h3><a href="/post">Title</a></h3>
<time datetime="2026-04-23">23 April 2026</time>
<p>Description...</p>
</article>
</li>
</ol>
A project card:
<article>
<header>
<h2>Project name</h2>
<p>Frontend · 2025</p>
</header>
<p>Description of what I did there.</p>
<footer>
<a href="https://...">Visit</a>
</footer>
</article>
no class Each tag describes its purpose.
Hand rule
If you're inventing a class like .wrapper, .container, .inner, or .box, ask yourself if it's really a <div> or if it could be <article>, <section>, <aside>, <nav>, or <figure>.
80% of the time, there is a better label.