Struktura Dokumentu HTML5 i Kluczowe Tagi Treści — Kompletny Szablon Razor Page

Kąt widzenia: co musi znaleźć się w każdym pliku HTML i dlaczego — od DOCTYPE po tagi treści — z gotowym szablonem
_Layout.cshtmldla ASP.NET Core
Przykład przewodni: kompletna struktura strony produktu w sklepie
DOCTYPE — deklaracja na początku każdego pliku HTML
<!DOCTYPE html>
Ta jedna linia musi być pierwszą linią każdego pliku HTML — przed <html>, przed komentarzami, przed wszystkim.
Mówi przeglądarce: “to jest dokument HTML5, interpretuj go zgodnie ze standardem HTML5”. Bez DOCTYPE przeglądarka przełącza się w Quirks Mode — tryb kompatybilności z przeglądarkami z lat 90., który renderuje strony inaczej niż standard. Efekt: układ CSS wygląda inaczej w różnych przeglądarkach i trudno debugować.
Starsze standardy miały długie DOCTYPE:
<!-- HTML 4.01 Strict — archaiczne -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
HTML5 upraszcza to do <!DOCTYPE html>. Tylko tyle. Nie pamiętaj starszych form — HTML5 to standard od 2014 roku.
Element <html> — korzeń dokumentu
<!DOCTYPE html>
<html lang="pl">
...
</html>
Atrybut lang jest obowiązkowy w dobrej praktyce:
- Czytniki ekranu dobierają wymowę i akcent na podstawie
lang - Przeglądarki wyświetlają poprawny słownik dla
spellcheck - Wyszukiwarki lepiej indeksują treść
Wartości: lang="pl" (polski), lang="en" (angielski), lang="de" (niemiecki). Pełna lista: BCP 47 language tags.
W Razor Layout (_Layout.cshtml) zawsze ustaw lang:
<html lang="@CultureInfo.CurrentCulture.TwoLetterISOLanguageName">
Sekcja <head> — metadane dokumentu
<head> zawiera informacje dla przeglądarki i robotów — nic w <head> nie jest widoczne bezpośrednio użytkownikowi (z wyjątkiem tytułu na karcie).
<meta charset="UTF-8"> — kodowanie znaków
<meta charset="UTF-8">
Pierwsza rzecz w <head> — przed jakimkolwiek tekstem. Mówi przeglądarce, jak interpretować bajty pliku. UTF-8 obsługuje polskie znaki (ą, ę, ó, ś, ź, ż, ć, ń, ł), emoji i praktycznie wszystkie języki świata.
Bez tego — polskie znaki mogą wyświetlać się jako Ä™, ó, Ĺ‚ itp. (błąd kodowania).
<meta name="viewport"> — responsywność na urządzeniach mobilnych
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Bez tego tagu przeglądarka mobilna zakłada, że strona ma szerokość 980px (jak desktop) i skaluje ją w dół — tekst staje się mikroskopijny. Z tym tagiem — strona ma szerokość urządzenia i jest czytelna.
width=device-width — szerokość viewportu = szerokość ekranu urządzeniainitial-scale=1.0 — brak domyślnego powiększenia
To jest warunek konieczny, żeby CSS media queries działały prawidłowo.
<title> — tytuł strony
<title>Klawiatura TKL Cherry MX Red — Sklep</title>
Wyświetla się w:
- Karcie przeglądarki
- Wynikach wyszukiwania Google (niebieski link)
- Zakładkach (Bookmarks)
- Udostępnieniach w mediach społecznościowych
Dobry tytuł: Temat strony — Nazwa witryny. Dla .NET:
<!-- Razor _Layout.cshtml -->
<title>@ViewData["Title"] — Sklep</title>
<!-- Razor Page lub View -->
@{
ViewData["Title"] = "Klawiatura TKL Cherry MX Red";
}
<meta name="description"> — opis dla wyszukiwarek
<meta name="description" content="Klawiatura mechaniczna TKL z przełącznikami Cherry MX Red. Podświetlenie RGB, anti-ghosting. Cena: 299 zł. Dostawa w 24h.">
Wyświetla się jako szary opis pod tytułem w wynikach Google. Max ~160 znaków. Nie wpływa bezpośrednio na pozycję w Google, ale wpływa na klikalność (CTR).
<link> — zewnętrzne zasoby
<!-- Arkusz stylów CSS -->
<link rel="stylesheet" href="/css/style.css">
<!-- Favicon — ikona w karcie przeglądarki -->
<link rel="icon" type="image/png" href="/img/favicon.png">
<link rel="apple-touch-icon" href="/img/apple-touch-icon.png">
<!-- Preload — pobierz zasób z wyprzedzeniem -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<!-- Canonical — mówi Google, który URL jest "oficjalny" przy duplikatach -->
<link rel="canonical" href="https://sklep.pl/products/keyboards/tkl-mx-red">
Open Graph — podglądy w mediach społecznościowych
<meta property="og:title" content="Klawiatura TKL Cherry MX Red — Sklep">
<meta property="og:description" content="Kompaktowa klawiatura mechaniczna. Cena: 299 zł.">
<meta property="og:image" content="https://sklep.pl/img/kb-tkl-og.jpg">
<meta property="og:url" content="https://sklep.pl/products/keyboards/tkl-mx-red">
<meta property="og:type" content="product">
Te tagi decydują o tym, jak strona wygląda po udostępnieniu na Facebook, Twitter, LinkedIn, Slack. Bez nich — social media pokażą losowe zdjęcie i brak opisu.
<script> — JavaScript
<!-- ❌ W <head> bez atrybutów — blokuje renderowanie -->
<script src="/js/app.js"></script>
<!-- ✅ defer — pobiera równolegle, wykonuje po załadowaniu DOM -->
<script src="/js/app.js" defer></script>
<!-- ✅ async — pobiera równolegle, wykonuje natychmiast po pobraniu -->
<script src="/js/analytics.js" async></script>
<!-- ✅ Lub na końcu <body> — stara metoda, defer jest lepsza -->
defer — skrypt czeka na pełny DOM, wykonuje się w kolejności. Właściwy wybór dla większości skryptów.async — skrypt wykonuje się jak najszybciej, może przerywać parsowanie HTML. Dla niezależnych skryptów (analytics, reklamy).
Kluczowe tagi treści w <body>
Nagłówki <h1>–<h6>
<h1>Klawiatura TKL Cherry MX Red</h1>
<h2>Specyfikacja techniczna</h2>
<h3>Przełączniki</h3>
<h3>Podświetlenie</h3>
<h2>Opinie klientów</h2>
<h3>Ocena 5/5 — Jan K.</h3>
Jeden <h1> na stronę. <h2>–<h6> mogą się powtarzać. Hierarchia musi być zachowana.
Akapit <p>
<p>
Klawiatura mechaniczna TKL z przełącznikami Cherry MX Red —
idealna do pracy i gier. Kompaktowy układ bez bloku numerycznego
zostawia więcej miejsca na biurku dla myszy.
</p>
Przeglądarki dodają margines powyżej i poniżej <p> — to jest domyślny styl, można go nadpisać CSS.
Linki <a>
<!-- Link zewnętrzny -->
<a href="https://www.cherry.de/pl"
rel="noopener noreferrer"
target="_blank">
Producent Cherry
</a>
<!-- Link wewnętrzny -->
<a href="/products/keyboards">Wróć do klawiatur</a>
<!-- Link do emaila -->
<a href="mailto:kontakt@sklep.pl">Napisz do nas</a>
<!-- Link do telefonu -->
<a href="tel:+48123456789">+48 123 456 789</a>
<!-- Link do sekcji na tej samej stronie (anchor) -->
<a href="#reviews">Przejdź do opinii</a>
<section id="reviews">...</section>
rel="noopener noreferrer" na linkach target="_blank" — blokuje dostęp otwartej strony do window.opener. To jest wymóg bezpieczeństwa — bez tego otwarta strona może przekierować oryginalną zakładkę.
Obrazy <img>
<img
src="/img/keyboard-tkl.jpg"
alt="Klawiatura TKL Cherry MX Red — widok z góry na białym tle"
width="800"
height="600"
loading="lazy"
>
alt— obowiązkowy. Opisuje obraz dla niewidomych i gdy obraz się nie ładuje. Dla obrazów dekoracyjnych:alt=""(pusty, ale obecny).widthiheight— zapobiega Layout Shift (CLS) — przeglądarka rezerwuje miejsce przed załadowaniem obrazuloading="lazy"— ładuj tylko gdy obraz wchodzi w viewport (poniżej fold). Dla pierwszego obrazu na stronie (above fold) — pomińlazy.
Formatowanie tekstu
<!-- Semantyczne — mają znaczenie -->
<strong>Ważna informacja</strong> <!-- duże znaczenie, domyślnie bold -->
<em>Klawiatura</em> <!-- nacisk/kursywa -->
<mark>Promocja -20%</mark> <!-- zaznaczenie/highlight -->
<del>349 zł</del> <!-- przekreślony, stara cena -->
<ins>279 zł</ins> <!-- wstawiony tekst, nowa cena -->
<code>Console.WriteLine()</code> <!-- fragment kodu -->
<abbr title="Ten-Key-Less">TKL</abbr> <!-- skrót z rozwinięciem -->
<small>*Oferta ważna do 31.03.2026</small> <!-- drobny druk -->
<sup>2</sup> <!-- indeks górny (m²) -->
<sub>2</sub> <!-- indeks dolny (H₂O) -->
<!-- Prezentacyjne — tylko wizualne, unikaj -->
<b>pogrubiony</b> <!-- użyj strong zamiast -->
<i>kursywa</i> <!-- użyj em zamiast, chyba że to nazwa techniczna -->
<strong> vs <b>: oba domyślnie bold, ale <strong> znaczy “ważne” (czytnik ekranu może to zaakcentować), <b> znaczy tylko “pogrubione wizualnie”.
Tabele
<table>
<caption>Specyfikacja klawiatur mechanicznych</caption>
<thead>
<tr>
<th scope="col">Model</th>
<th scope="col">Przełączniki</th>
<th scope="col">Układ</th>
<th scope="col">Cena</th>
</tr>
</thead>
<tbody>
<tr>
<td>TKL MX Red</td>
<td>Cherry MX Red</td>
<td>87 klawiszy</td>
<td>299 zł</td>
</tr>
<tr>
<td>Full-size MX Blue</td>
<td>Cherry MX Blue</td>
<td>104 klawisze</td>
<td>349 zł</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">Ceny brutto, dostawa od 19 zł</td>
</tr>
</tfoot>
</table>
scope="col" na <th> — mówi czytnikowi ekranu, że to nagłówek kolumny. <caption> — widoczny tytuł tabeli.
Tabele służą do danych tabelarycznych — nie do layoutu strony. Layout robimy przez CSS Grid i Flexbox.
Kompletny szablon _Layout.cshtml dla ASP.NET Core
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewData["Title"] — Sklep</title>
<meta name="description" content="@ViewData["Description"]">
<!-- Open Graph -->
<meta property="og:title" content="@ViewData["Title"] — Sklep">
<meta property="og:description" content="@ViewData["Description"]">
<meta property="og:image" content="@ViewData["OgImage"] ?? "/img/default-og.jpg"">
<!-- Favicon -->
<link rel="icon" type="image/png" href="/img/favicon.png">
<!-- Styles -->
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true">
<!-- Render Section: strony mogą dodać własne style -->
@await RenderSectionAsync("Styles", required: false)
</head>
<body>
<header class="site-header">
<a href="/" class="brand">
<img src="/img/logo.svg" alt="Sklep — strona główna" width="120" height="40">
</a>
<nav aria-label="Nawigacja główna">
<ul>
<li><a href="/products" asp-area="" asp-controller="Products" asp-action="Index">Produkty</a></li>
<li><a href="/brands">Marki</a></li>
<li>
<a href="/cart" aria-label="Koszyk">
Koszyk
<span class="cart-count" id="cart-count">@ViewData["CartCount"]</span>
</a>
</li>
</ul>
</nav>
</header>
<main>
@if (TempData["SuccessMessage"] != null)
{
<div role="alert" class="alert alert-success">
@TempData["SuccessMessage"]
</div>
}
@if (TempData["ErrorMessage"] != null)
{
<div role="alert" class="alert alert-error">
@TempData["ErrorMessage"]
</div>
}
@RenderBody()
</main>
<footer class="site-footer">
<nav aria-label="Linki stopki">
<ul>
<li><a href="/about">O firmie</a></li>
<li><a href="/privacy">Polityka prywatności</a></li>
<li><a href="/terms">Regulamin</a></li>
<li><a href="/contact">Kontakt</a></li>
</ul>
</nav>
<address>
<a href="mailto:kontakt@sklep.pl">kontakt@sklep.pl</a>
</address>
<p><small>© @DateTime.Now.Year Sklep Sp. z o.o.</small></p>
</footer>
<!-- Scripts na końcu body — defer by default -->
<script src="~/js/site.js" asp-append-version="true" defer></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Kilka elementów warte uwagi:
asp-append-version="true"— ASP.NET Core Tag Helper dodaje hash do URL pliku (cache busting):site.css?v=abc123role="alert"na komunikatach — czytniki ekranu natychmiast ogłaszają jego zawartość@DateTime.Now.Yearw copyright — automatycznie aktualny rok@RenderSectionAsync("Scripts", required: false)— strony mogą wstrzykiwać własne skrypty
Podsumowanie: co musi być w każdym pliku HTML
<!DOCTYPE html> <!-- 1. Deklaracja HTML5 -->
<html lang="pl"> <!-- 2. Język strony -->
<head>
<meta charset="UTF-8"> <!-- 3. Kodowanie — PIERWSZA linia head -->
<meta name="viewport"
content="width=device-width, initial-scale=1.0"> <!-- 4. Mobilność -->
<title>Tytuł strony</title> <!-- 5. Tytuł -->
<!-- link, meta, script z defer -->
</head>
<body>
<!-- Treść strony -->
</body>
</html>
Punkty 1–5 są obowiązkowe. Bez nich strona działa, ale nie spełnia standardów HTML5 i może zachowywać się nieprzewidywalnie w różnych przeglądarkach i urządzeniach.
Następny post: Formularze HTML5 w ASP.NET Core — pola, walidacja i model binding — wszystkie typy pól formularza, walidacja po stronie klienta przez atrybuty HTML5, i jak formularz HTML łączy się z modelem C# przez model binding.
🚀 Co dalej?
Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.
- 🗺️ Pobierz darmową roadmapę Junior .NET Developer — 12 kroków od podstaw C# do pierwszej pracy: dev-hobby.pl
- 🎬 Subskrybuj kanał YouTube — nowe filmy co tydzień.
Zamień wiedzę w umiejętności
Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.
Pobieram roadmapę →
1 comment