Jeśli używałeś <div> do wszystkiego — opakowania strony, nawigacji, kontenera artykułu, paska bocznego — nie jesteś sam. To był domyślny ruch przez lata. Ale HTML ma właściwe elementy semantyczne od czasów HTML5 i ich używanie sprawia, że kod jest łatwiejszy do czytania, lepszy dla SEO i naprawdę bardziej dostępny. Przyjrzyjmy się elementom, które naprawdę mają znaczenie.
Słowo „semantyczny" oznacza po prostu, że element niesie ze sobą znaczenie wykraczające poza jego wizualną prezentację. <div> nic nie oznacza — to ogólny blok. <nav> mówi przeglądarce, wyszukiwarkom i technologiom wspomagającym: „tutaj są linki nawigacyjne". Ten kontekst nic cię nie kosztuje, a przynosi wielorakie korzyści.
Dlaczego Semantyka Ma Znaczenie
Trzy realne korzyści, nie teoretyczne:
- SEO. Wyszukiwarki używają struktury dokumentu do rozumienia hierarchii treści. Element
<main>sygnalizuje treść główną.<article>wewnątrz niego sygnalizuje samodzielną całość. Google używa tych sygnałów przy rankingowaniu stron. - Dostępność. Czytniki ekranu udostępniają użytkownikom regiony orientacyjne. Dzięki
<nav>,<main>i<aside>na miejscu, użytkownicy klawiatury mogą przeskakiwać bezpośrednio do sekcji, której szukają — bez tabulowania przez każdy link na stronie. - Łatwość utrzymania. Nowy programista czytający twój szablon od razu rozumie strukturę strony.
<header>/<main>/<footer>samo się dokumentuje w sposób, w jaki<div class="top">/<div class="content">/<div class="bottom">nie jest w stanie.
Podstawowe Elementy Układu
Te pięć elementów obsługuje zewnętrzny szkielet większości stron. Używaj ich na każdej stronie, a już wygrałeś połowę semantycznej bitwy:
<body>
<header>
<a href="/" class="logo">MyBlog</a>
<nav>
<ul>
<li><a href="/articles">Articles</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<!-- Primary page content goes here -->
</main>
<aside>
<!-- Sidebar: related links, ads, author bio -->
</aside>
<footer>
<p>© 2026 MyBlog. All rights reserved.</p>
</footer>
</body><header>. Treść wprowadzająca dla strony lub sekcji. Zazwyczaj zawiera logo, tytuł strony i główną nawigację. Możesz go również używać wewnątrz<article>dla własnego bloku nagłówka artykułu.<nav>. Zestaw linków nawigacyjnych. Nie każda grupa linków potrzebuje<nav>— używaj go dla głównych bloków nawigacyjnych, takich jak nawigacja po stronie lub paginacja.<main>. Dominująca treść strony. Na każdej stronie powinien być tylko jeden<main>i nie powinien zawierać niczego powtarzającego się na stronach (nagłówek, nawigacja, stopka).<aside>. Treść luźno powiązana z treścią główną. Paski boczne, cytaty wyróżnione, powiązane artykuły. Czytniki ekranu udostępniają to jako punkt orientacyjny uzupełniający.<footer>. Stopka strony lub sekcji. Może zawierać informacje o prawach autorskich, nawigację pomocniczą, linki kontaktowe lub krótką notatkę o autorze.
<header> i <footer> nie są ograniczone do poziomu strony. Każdy <article> lub <section> może mieć własny <header> i <footer>. Jest to szczególnie przydatne dla podpisów wpisów na blogu i metadanych na poziomie artykułu.article vs section — Kiedy Używać Każdego
To jest element, który sprawia ludziom najwięcej trudności. Reguła kciuka, która faktycznie działa: jeśli treść miałaby sens, gdybyś ją syndykował samodzielnie (np. opublikował jako wpis RSS lub udostępnił na innej stronie), to jest to <article>. Jeśli ma sens tylko jako część większej całości, to jest to <section>.
<!-- article: self-contained, could stand alone -->
<article>
<header>
<h2>Understanding HTTP/2 Push</h2>
<p>By Alice Chen — <time datetime="2026-03-15">March 15, 2026</time></p>
</header>
<p>HTTP/2 Server Push lets the server send resources...</p>
<footer>
<p>Tagged: <a href="/tags/http">HTTP</a>, <a href="/tags/performance">Performance</a></p>
</footer>
</article>
<!-- section: thematic grouping within a page -->
<section>
<h2>Related Articles</h2>
<ul>
<li><a href="/http3-quic">HTTP/3 and QUIC Explained</a></li>
<li><a href="/cdn-strategy">CDN Strategy for Global Apps</a></li>
</ul>
</section><section> powinien zawsze mieć nagłówek (<h2> do <h6>). Jeśli twoja sekcja nie ma nagłówka, to zazwyczaj znak, że powinieneś użyć <div>. Specyfikacja WHATWG jest jasna: <section> służy do tematycznych grupowań, a nie do dowolnych podziałów układu.
figure, figcaption, time i address
Cztery elementy, które programiści często pomijają, a regularnie ich potrzebują:
<!-- figure + figcaption: images, code blocks, diagrams, charts -->
<figure>
<img src="/images/latency-chart.png" alt="P99 latency over 24 hours showing a spike at 14:30">
<figcaption>Figure 1: API latency during the Tuesday incident (UTC).</figcaption>
</figure>
<!-- A code block as a figure (totally valid) -->
<figure>
<pre><code>const result = await db.query('SELECT * FROM users WHERE active = true');</code></pre>
<figcaption>Listing 1: Basic active user query.</figcaption>
</figure>
<!-- time: machine-readable dates and times -->
<p>Published <time datetime="2026-04-16T09:00:00Z">April 16, 2026</time></p>
<p>Sale ends in <time datetime="PT2H30M">2 hours 30 minutes</time></p>
<!-- address: contact info for nearest article or body ancestor -->
<address>
Written by <a href="mailto:[email protected]">Alice Chen</a>.<br>
123 Dev Street, San Francisco, CA.
</address><figure>. Dowolna samodzielna treść, do której odwołuje się główny przepływ — obrazy, listingi kodu, wykresy, filmy. Kluczowe: można by ją przenieść do dodatku bez zakłócania toku czytania.<figcaption>. Podpis dla<figure>. Musi być pierwszym lub ostatnim potomkiem<figure>. Zapewnia semantyczne powiązanie między podpisem a treścią, czego<p>pod obrazem nie robi.<time>. Daty czytelne dla człowieka z atrybemdatetimeczytelnym dla maszyny. Wartośćdatetimeużywa formatu ISO 8601. Wyszukiwarki używają tego do oznaczenia wydarzeń i sygnałów świeżości.<address>. Dane kontaktowe dla najbliższego przodka<article>(lub całego<body>). Nie jest to element adresu ogólnego przeznaczenia — jest przeznaczony konkretnie dla danych kontaktowych autora treści lub właściciela strony.
Antywzorzec Divitis
„Divitis" to coś, co dzieje się, gdy każdy element w twoim HTML jest <div>. Oto realny przykład przed i po, który pokazuje problem:
<!-- Before: divitis -->
<div class="page">
<div class="header">
<div class="brand">TechBlog</div>
<div class="nav">
<div class="nav-item"><a href="/posts">Posts</a></div>
</div>
</div>
<div class="post">
<div class="post-title">Why TypeScript Is Worth It</div>
<div class="post-meta">By Bob — Jan 2026</div>
<div class="post-body">TypeScript adds static types to JavaScript...</div>
</div>
</div>
<!-- After: semantic HTML -->
<body>
<header>
<span class="brand">TechBlog</span>
<nav>
<a href="/posts">Posts</a>
</nav>
</header>
<main>
<article>
<header>
<h1>Why TypeScript Is Worth It</h1>
<p>By Bob — <time datetime="2026-01-10">January 10, 2026</time></p>
</header>
<p>TypeScript adds static types to JavaScript...</p>
</article>
</main>
</body>Wersja semantyczna jest faktycznie krótsza, wymaga mniej nazw klas CSS i daje przeglądarkom oraz narzędziom wspomagającym wszystko, czego potrzebują do zrozumienia struktury strony. Nadal możesz stylizować wszystko dokładnie tak samo za pomocą CSS — elementy semantyczne nie narzucają żadnych ograniczeń wizualnych.
Role ARIA — Ostateczność, Nie Pierwszy Krok
Role ARIA pozwalają dodawać znaczenie semantyczne do elementów, które go natywnie nie mają. Problem w tym, że programiści często sięgają po ARIA, gdy natywny element HTML wykonałby pracę lepiej. Pierwsza zasada ARIA: nie używaj ARIA, jeśli możesz użyć natywnego HTML.
<!-- Wrong: using ARIA where native HTML works -->
<div role="navigation">
<a href="/home">Home</a>
</div>
<!-- Right: just use the semantic element -->
<nav>
<a href="/home">Home</a>
</nav>
<!-- ARIA is appropriate here: custom widget with no HTML equivalent -->
<div
role="tablist"
aria-label="Code examples"
>
<button role="tab" aria-selected="true" aria-controls="panel-js">JavaScript</button>
<button role="tab" aria-selected="false" aria-controls="panel-py">Python</button>
</div>Używaj ARIA dla interaktywnych widżetów, których natywny HTML nie obsługuje — panele z zakładkami, pola kombi, widoki drzew, wybieraki dat. W przypadku strukturalnych punktów orientacyjnych, takich jak nawigacja, nagłówki i treść główna, zawsze polegaj na natywnych elementach.
Kompletna Struktura Strony Wpisu Blogowego
Tak wygląda w pełni semantyczna strona wpisu blogowego. To wzorzec stosowany na stronach, które dobrze wypadają w audytach dostępności bez dodatkowego wysiłku:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Why TypeScript Is Worth It — TechBlog</title>
</head>
<body>
<header>
<a href="/" class="logo">TechBlog</a>
<nav aria-label="Site navigation">
<ul>
<li><a href="/posts">Posts</a></li>
<li><a href="/topics">Topics</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header>
<h1>Why TypeScript Is Worth It</h1>
<address>
By <a rel="author" href="/authors/bob">Bob Martinez</a>
</address>
<p>Published <time datetime="2026-01-10">January 10, 2026</time></p>
</header>
<section>
<h2>The Setup Cost Is Real but Front-Loaded</h2>
<p>TypeScript adds a compilation step and requires type annotations...</p>
<figure>
<pre><code>interface User {
id: number;
name: string;
email: string;
}</code></pre>
<figcaption>Listing 1: A typed User interface catches shape errors at compile time.</figcaption>
</figure>
</section>
<section>
<h2>Where TypeScript Pays Off</h2>
<p>The ROI kicks in as team size and codebase complexity grows...</p>
</section>
<footer>
<p>
Tagged: <a href="/tags/typescript">TypeScript</a>,
<a href="/tags/javascript">JavaScript</a>
</p>
</footer>
</article>
<aside aria-label="Related articles">
<h2>You Might Also Like</h2>
<ul>
<li><a href="/ts-vs-js">TypeScript vs JavaScript — A Practical Comparison</a></li>
<li><a href="/ts-generics">TypeScript Generics Explained</a></li>
</ul>
</aside>
</main>
<footer>
<nav aria-label="Footer navigation">
<a href="/privacy">Privacy</a>
<a href="/terms">Terms</a>
</nav>
<p><small>© 2026 TechBlog</small></p>
</footer>
</body>
</html>Zwróć uwagę na podwójne użycie <header> i <footer> — raz na poziomie strony, raz wewnątrz <article>. To zamierzone i poprawne. Zwróć też uwagę na dwa elementy <nav> z odrębnymi wartościami aria-label — zapobiega to temu, by czytniki ekranu listowały dwa identyczne regiony „nawigacja".
Szybka Pomoc: Przydatne Narzędzia
Jeśli pracujesz z HTML i chcesz wyczyścić lub zwalidować swój kod, Formater HTML ładnie go sformatuje i poprawi, a Walidator HTML wykryje błędy strukturalne, takie jak niezamknięte tagi i brakujące wymagane atrybuty. Dla głębszego audytu dostępności, web.dev/accessibility oferuje doskonałe diagnostyki i wyjaśnienia.
Podsumowanie
Semantyczny HTML nie polega na przestrzeganiu reguł dla samych reguł — chodzi o pisanie kodu, który wyraźnie komunikuje się z przeglądarkami, wyszukiwarkami, narzędziami wspomagającymi i kolejnym programistą czytającym twój szablon. Podstawowe elementy są proste: <header>, <nav>, <main>, <article>, <section>, <aside> i <footer> obejmują zdecydowaną większość rzeczywistych struktur stron. Dodaj <figure>, <time> i <address> tam, gdzie pasują, sięgaj po ARIA tylko wtedy, gdy natywny HTML zawodzi, a będziesz mieć kod, z którym naprawdę przyjemnie się pracuje.