Таблица в HTML — это блок разметки на теге <table>, который выводит данные сеткой из строк и столбцов. Строку задает <tr>, ячейку данных — <td>, ячейку-заголовок — <th>. Внешний вид (границы, отступы, цвета) задается не тегами, а через CSS. Ниже — минимальный рабочий пример, разбор тегов и атрибутов, объединение ячеек, стилизация и доступность.
Содержание
Важно сразу развести две вещи. Разметка (HTML) отвечает за структуру и смысл: где строка, где заголовок, где данные. Оформление (CSS) отвечает за вид: рамки, отступы, чередование фона. Старые атрибуты border, cellpadding, cellspacing, align у <table> в HTML5 не используются — их заменил CSS.
Минимальная рабочая таблица
Начнем с законченного примера, который можно скопировать и открыть в браузере.
<table>
<caption>Цены на канцтовары</caption>
<thead>
<tr>
<th scope="col">Товар</th>
<th scope="col">Цена, руб.</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Карандаш</th>
<td>20</td>
</tr>
<tr>
<th scope="row">Линейка</th>
<td>30</td>
</tr>
</tbody>
</table>
В браузере это отрисует подпись сверху, строку заголовков и две строки данных. Пока без рамок — по умолчанию границ у таблицы нет, их добавит CSS ниже.
Разберем теги по ролям:
<table>— контейнер всей таблицы, все остальные теги лежат внутри него.<caption>— подпись таблицы, ставится сразу после<table>; выводится над таблицей.<thead>,<tbody>,<tfoot>— секции: шапка, тело и подвал (итоги). Они группируют строки по смыслу.<tr>— строка таблицы (table row); число строк равно числу пар<tr>.<th>— ячейка-заголовок; по умолчанию текст в ней жирный и по центру.<td>— ячейка данных (table data).
Число <td> и <th> в одной строке задает количество столбцов. Строки должны быть согласованы по числу ячеек, иначе разметка «поедет».
Секции thead, tbody, tfoot
Секции нужны для семантики и стилей, а не для внешнего вида сами по себе. <thead> — строки заголовков, <tbody> — основные данные, <tfoot> — итоговые строки (сумма, всего). Порядок в коде: <caption>, затем <thead>, <tfoot> или <tbody> — современные браузеры отрисуют подвал внизу независимо от места в коде, но по стандарту его принято ставить после <thead>.
Раньше ожидалось, что при длинной таблице браузер зафиксирует шапку и подвал при прокрутке, а при печати повторит их на каждой странице. На практике браузеры так делают не всегда — фиксацию шапки обычно решают через CSS (position: sticky), а не расчетом на поведение секций.
<tbody> можно использовать несколько раз — это удобно, чтобы разбить длинные данные на логические группы, сохранив одну таблицу.
Объединение ячеек: colspan и rowspan
Две частые задачи — растянуть ячейку на несколько столбцов или строк. Для этого есть атрибуты colspan (по горизонтали) и rowspan (по вертикали).
<table>
<tbody>
<tr>
<th scope="row">Итого</th>
<td colspan="2">1168,80 руб.</td>
</tr>
<tr>
<th scope="row" rowspan="2">Овощи</th>
<td>Томаты</td>
<td>69,00</td>
</tr>
<tr>
<td>Огурцы</td>
<td>48,00</td>
</tr>
</tbody>
</table>
Здесь colspan="2" слил две ячейки в одну по ширине, а rowspan="2" растянул заголовок «Овощи» на две строки. Правило простое: если ячейка перекрывает соседнюю по строке или столбцу через span, эту соседнюю ячейку в коде уже не пишут — иначе появится лишний столбец. Оба атрибута принимают целое число от 1 и выше.
Стилизация таблицы через CSS
Границы, отступы и цвета задаются в CSS. Базовый набор, который делает таблицу читаемой:
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ccc;
padding: 8px 12px;
text-align: left;
}
tbody tr:nth-child(even) {
background: #f5f5f5;
}
caption {
caption-side: top;
padding: 6px;
font-weight: 600;
}
Ключевые свойства:
border-collapse: collapseсхлопывает двойные рамки соседних ячеек в одну линию. Значение по умолчанию —separate, при нем между ячейками остается зазор, а его размер задаетborder-spacing(работает только приseparate).paddingу<th>/<td>— внутренний отступ между содержимым и границей ячейки. У<table>его задавать смысла нет, он ставится на ячейки.nth-child(even)красит четные строки тела — получаются «полосатые» строки (zebra), их проще читать глазами.caption-sideдвигает подпись:top— над таблицей (по умолчанию),bottom— под ней.
Адаптивность: горизонтальный скролл
Широкая таблица на телефоне ломает верстку и вызывает горизонтальную прокрутку всей страницы. Надежный прием — обернуть таблицу в контейнер с прокруткой по горизонтали, тогда скроллится только сама таблица.
<div class="table-wrap">
<table>
<!-- строки таблицы -->
</table>
</div>
.table-wrap {
overflow-x: auto;
}
table {
min-width: 480px;
}
overflow-x: auto добавляет полосу прокрутки контейнеру, когда таблица шире экрана, а min-width не дает столбцам схлопнуться в нечитаемую кашу. Это работает во всех современных браузерах и не требует JavaScript. Полностью перестраивать таблицу в «карточки» под мобильный тоже можно, но это более трудоемкий прием и оправдан не всегда.
Доступность: caption и scope
Таблица данных должна быть понятна не только глазами, но и программе чтения с экрана. Два простых шага закрывают большую часть задачи.
Первое — <caption> как краткое описание, о чем таблица. Скринридер зачитает его до содержимого, и пользователю не придется угадывать смысл по ячейкам. Если по дизайну подпись не нужна визуально, ее не удаляют из разметки, а скрывают классом (например, приемом visually-hidden) — для программы чтения она останется.
Второе — атрибут scope у заголовочных ячеек: scope="col" для заголовка столбца и scope="row" для заголовка строки. Он связывает данные с их заголовками, и скринридер читает ячейку вместе с нужным заголовком. Для сложных таблиц с многоуровневой шапкой есть более точная связка через id у <th> и headers у <td>, но для обычных таблиц достаточно scope.
Заголовки <th> не используют ради жирного шрифта: это семантический тег. Если нужен просто жирный текст в ячейке данных — это <td> плюс CSS, а не <th>.
Атрибуты для работы с таблицами
| Атрибут | На каком теге | Что делает |
|---|---|---|
colspan |
td, th |
Объединяет ячейки по горизонтали; целое число >= 1 |
rowspan |
td, th |
Объединяет ячейки по вертикали; целое число >= 1 |
scope |
th |
К чему относится заголовок: col, row, colgroup, rowgroup |
headers |
td, th |
Связь ячейки с заголовками по их id (сложные таблицы) |
span |
col, colgroup |
На сколько столбцов распространяется группа; по умолчанию 1 |
Атрибуты border, cellpadding, cellspacing, width, align, bgcolor у таблицы в HTML5 устарели — их роль полностью взял на себя CSS.
Выводы
- Разметка задает структуру таблицы (
table,tr,th,td, секцииthead/tbody/tfoot), а весь внешний вид — рамки, отступы, цвета — задается через CSS. <th>— это заголовок по смыслу, а не способ сделать текст жирным;<td>— ячейка данных.colspanобъединяет ячейки по горизонтали,rowspan— по вертикали; перекрытые ячейки в коде не дублируют.- Базовая стилизация:
border-collapse: collapse,paddingна ячейках, полосатые строки черезnth-child(even). - Для мобильных — обертка с
overflow-x: auto; для доступности —<caption>иscopeу заголовков.
Где применяется / связь с практикой
Таблицы нужны везде, где данные удобнее показать сеткой: прайсы, сравнения тарифов, расписания, отчеты, спецификации товаров. Верстальщик и фронтенд-разработчик собирают их вручную и стилизуют под макет, поэтому уверенное владение тегами таблиц и CSS — базовый навык, который спрашивают на собеседованиях junior-уровня.
Освойте тему на практике
Разобрать разметку и стилизацию на практике, с проверкой кода наставником, помогает курс «HTML/CSS: Профессиональная веб-верстка». Посмотреть формат занятий и темы можно на открытых уроках Otus — они бесплатные и проходят регулярно.
FAQ
Чем <th> отличается от <td>?
<th> — заголовочная ячейка, она несет смысл «это шапка строки или столбца» и по умолчанию отрисовывается жирной. <td> — обычная ячейка данных. Разница не в шрифте, а в семантике: скринридеры и поисковые системы читают <th> как заголовок.
Как сделать так, чтобы широкая таблица не ломала верстку на телефоне?
Обернуть таблицу в блок с overflow-x: auto и задать таблице min-width. Тогда прокручиваться будет только таблица внутри своего контейнера, а не вся страница.
Нужны ли <thead>, <tbody> и <tfoot> в простой таблице?
Формально нет, таблица работает и без них. Но секции упрощают стилизацию (например, полосатые строки только для тела) и улучшают семантику, поэтому в реальном коде их обычно ставят.



