Cześć! Jeśli kiedykolwiek budowałeś tabele w HTML i zastanawiałeś się, jak sprawić, by były nie tylko ładne wizualnie, ale też semantycznie poprawne i przyjazne dla czytników ekranu, to tag <thead> jest właśnie tym elementem, który robi różnicę. <thead> służy do grupowania nagłówka tabeli, czyli wierszy z tytułami kolumn, i zawsze powinien być używany w połączeniu z <tbody> (treść główna) oraz opcjonalnie <tfoot> (stopka).
W tym rozbudowanym wpisie o programowaniu w HTML/CSS/JavaScript przyjrzymy się tagowi <thead> od podszewki: od podstawowego zastosowania, przez zaawansowane style CSS, po przykłady z JavaScriptem i wskazówki dotyczące dostępności WCAG. Znajdziesz tu mnóstwo przykładowego kodu, który możesz skopiować i przetestować. Gotowy? Zaczynamy!
Po co w ogóle używać <thead>? Podstawy semantyki HTML
W czystym HTML bez strukturyzacji tabela to po prostu zbiór elementów <tr>, <th> i <td>. Ale nowoczesne tabele potrzebują semantyki – czyli informacji dla przeglądarek, robotów wyszukiwarek i programów do odczytu ekranu (np. NVDA czy VoiceOver), co jest nagłówkiem, a co danymi. <thead> definiuje sekcję nagłówkową tabeli, która zazwyczaj zawiera jeden lub więcej wierszy <tr> z komórkami nagłówkowymi <th>.
Oto najważniejsze zasady użycia <thead> zgodnie ze specyfikacją HTML5:
- może być tylko jeden
<thead>na<table>, - musi być umieszczony po
<caption>i<colgroup>, ale przed<tbody>,<tfoot>lub luźnymi<tr>, - w środku musi znaleźć się co najmniej jeden element
<tr>, - znacznik zamykający
</thead>można pominąć, jeśli zaraz po nim następuje<tbody>lub<tfoot>.
Bez <thead> przeglądarka i czytniki ekranu nie mają pewności, że pierwszy wiersz to nagłówek – co oznacza gorszą dostępność i brak automatycznego powtarzania nagłówków przy drukowaniu. Obsługa <thead> jest pełna we wszystkich nowoczesnych przeglądarkach (Chrome, Firefox, Safari, Edge).
Prosty przykład: podstawowa tabela z <thead>
Oto klasyczny przykład tabeli z nagłówkiem, treścią i stopką – skopiuj i otwórz w przeglądarce:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Przykład tabeli z thead</title>
</head>
<body>
<table border="1">
<thead>
<tr>
<th scope="col">Miesiąc</th>
<th scope="col">Oszczędności</th>
</tr>
</thead>
<tbody>
<tr>
<td>Styczeń</td>
<td>100 zł</td>
</tr>
<tr>
<td>Luty</td>
<td>80 zł</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Suma</td>
<td>180 zł</td>
</tr>
</tfoot>
</table>
</body>
</html>
Rezultat: nagłówek jest wyraźnie oddzielony, a stopka zawsze na dole – nawet przy długich tabelach. To podstawa, ale zobaczmy, jak to ulepszyć CSS-em.
Stylizacja <thead> za pomocą CSS – kolory, wyrównanie i responsywność
Domyślne style dla <thead> to display: table-header-group; vertical-align: middle; border-color: inherit;. Możesz je nadpisać, by nagłówek wyróżniał się tłem, kolorem czy pozycjonowaniem. Pamiętaj, że lepki nagłówek wymaga przewijanego kontenera.
Przykład 1 – kolorowanie sekcji tabeli
Nadaj różny kolor każdej sekcji – zielony nagłówek, niebieskie ciało, czerwona stopka:
<!DOCTYPE html>
<html lang="pl">
<head>
<style>
table, th, td { border: 1px solid #000; border-collapse: collapse; }
thead { background-color: #4CAF50; color: #fff; }
tbody { background-color: #2196F3; color: #fff; }
tfoot { background-color: #f44336; color: #fff; }
</style>
</head>
<body>
<table style="width: 100%;">
<thead>
<tr>
<th scope="col">Miesiąc</th>
<th scope="col">Oszczędności</th>
</tr>
</thead>
<tbody>
<tr><td>Styczeń</td><td>100 zł</td></tr>
<tr><td>Luty</td><td>80 zł</td></tr>
</tbody>
<tfoot>
<tr><td>Suma</td><td>180 zł</td></tr>
</tfoot>
</table>
</body>
</html>
Efekt: przejrzysty, profesjonalny wygląd z wyraźnym podziałem sekcji.
Przykład 2 – wyrównanie tekstu i pionowe pozycjonowanie w <thead>
Użyj text-align i vertical-align bezpośrednio na <thead> lub wierszu <tr> – idealne dla wysokich nagłówków:
<table style="width: 100%; border: 1px solid #000; border-collapse: collapse;">
<thead style="text-align: left; vertical-align: bottom; height: 100px; background: linear-gradient(to bottom, #ddd, #fff);">
<tr>
<th scope="col">Miesiąc</th>
<th scope="col">Oszczędności (w zł)</th>
</tr>
</thead>
<tbody>
<tr><td>Styczeń</td><td>100</td></tr>
<tr><td>Luty</td><td>80</td></tr>
</tbody>
</table>
Nagłówek jest wyrównany do lewej i dołu komórki – czytelne przy większej wysokości wiersza.
Responsywna tabela z lepką <thead>
Aby uzyskać nagłówek, który „przykleja się” podczas przewijania, ustaw na komórkach nagłówka position: sticky i top: 0:
thead th {
position: sticky;
top: 0;
background: #4CAF50;
z-index: 10;
}
Dodaj overflow: auto; max-height: 300px; do kontenera otaczającego tabelę (np. do <div>), dzięki czemu nagłówek pozostanie widoczny przy przewijaniu danych w <tbody>.
Zaawansowane przykłady – JavaScript i interaktywne tabele
<thead> świetnie współpracuje z JS – np. do sortowania kolumn. Poniżej prosty przykład sortowania po kliknięciu w nagłówek kolumny:
Przykład: sortowalna tabela z <thead>
Skopiuj, wklej i przetestuj w przeglądarce:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<style>
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #4CAF50; color: #fff; cursor: pointer; user-select: none; }
th:hover { background-color: #45a049; }
</style>
</head>
<body>
<table id="tabela">
<thead>
<tr>
<th scope="col" data-type="text">Owoc</th>
<th scope="col" data-type="number">Cena (zł)</th>
</tr>
</thead>
<tbody>
<tr><td>Jabłko</td><td>2.50</td></tr>
<tr><td>Banany</td><td>4.00</td></tr>
<tr><td>Truskawka</td><td>12.00</td></tr>
</tbody>
</table>
<script>
(function () {
const tabela = document.getElementById('tabela');
const theadCells = tabela.querySelectorAll('thead th');
const tbody = tabela.querySelector('tbody');
theadCells.forEach((th, index) => {
th.addEventListener('click', () => {
const type = th.getAttribute('data-type') || 'text';
const dir = th.getAttribute('data-dir') === 'asc' ? 'desc' : 'asc';
th.setAttribute('data-dir', dir);
const rows = Array.from(tbody.querySelectorAll('tr'));
rows.sort((a, b) => {
let A = a.children[index].textContent.trim();
let B = b.children[index].textContent.trim();
if (type === 'number') {
A = parseFloat(A.replace(',', '.')) || 0;
B = parseFloat(B.replace(',', '.')) || 0;
} else {
A = A.toLowerCase();
B = B.toLowerCase();
}
if (A < B) return dir === 'asc' ? -1 : 1;
if (A > B) return dir === 'asc' ? 1 : -1;
return 0;
});
// odświeżenie DOM
rows.forEach(row => tbody.appendChild(row));
});
});
})();
</script>
</body>
</html>
Kliknij nagłówek, aby posortować rosnąco lub malejąco – <thead> ułatwia wiązanie zdarzeń z komórkami nagłówków.
Dostępność (WCAG) i najlepsze praktyki z <thead>
Według WCAG 2.1, semantyczna struktura tabel z <thead>, <tbody> i <tfoot> znacząco poprawia dostępność. Dodaj atrybut scope="col" do komórek nagłówka <th>, aby czytniki ekranu poprawnie kojarzyły komórki danych z nagłówkami kolumn. W większości przypadków nie ma potrzeby dodawania ról ARIA, jeśli używasz poprawnych znaczników HTML.
Najlepsze praktyki
Stosuj poniższe wskazówki, aby zachować czytelność i dostępność tabel:
- używaj
<th>zamiast<td>w<thead>dla prawidłowych nagłówków, - w prostych tabelach ogranicz się do jednego wiersza nagłówka (więcej stosuj tylko w złożonych strukturach),
- dla danych zawsze łącz
<thead>z<tbody>(i opcjonalnie<tfoot>), - unikaj tabel do układu strony – do layoutu używaj Flexbox lub CSS Grid.
Unikaj typowych błędów: nie umieszczaj <tbody> przed <thead>; nie zapominaj o lang="pl" w dokumencie, aby ułatwić pracę technologiom asystującym.