Тег caption (от английского caption, «заголовок», «надпись») задаёт заголовок таблицы. Он записывается первым внутри table, до строк и до thead. Тег парный: закрывающий </caption> лучше писать всегда.
Заголовок таблицы выглядит просто, но ведёт себя не так, как абзац над таблицей: он выводится над таблицей или под ней, не входит в её рамку и не берёт её фон. О том, чем он отличается от заголовка h3 перед таблицей, рассказано в уроке «Секции таблицы: thead, tbody, tfoot и caption». Здесь разобрано то, чего в уроке нет: положение, выравнивание, ширина, закрепление при прокрутке и работа в адаптивной таблице.
<table>
<caption>Цены на чай</caption>
<tr><td>Чай</td><td>120</td></tr>
</table>
В этой статье
- Тег caption в HTML: что это и для чего нужен
- Где записывать тег caption: позиция в коде и на экране
- Атрибуты тега caption: align устарел, что писать вместо него
- caption-side и text-align: заголовок под таблицей и выравнивание текста
- Ширина, рамка и фон тега caption: что входит в таблицу, а что нет
- Закрепление caption при прокрутке таблицы вбок
- Тег caption в адаптивной таблице: почему заголовок сжимается
- Что записать внутри caption и как скрыть заголовок от глаз
- Частые ошибки с тегом caption
Тег caption в HTML: что это и для чего нужен
Заголовок нужен таблице, чтобы читатель сразу понял, о чём она: «Цены на чай», «Расписание на неделю», «Тарифы хостинга». Его записывают тегом caption, а не отдельным абзацем над таблицей. Тогда заголовок связан с этой таблицей и ни с какой другой, а скринридер зачитывает его как название таблицы.
<table>
<caption>Цены на чай</caption>
<tr><th>Товар</th><th>Цена</th></tr>
<tr><td>Чай</td><td>120</td></tr>
</table>
Заголовок один на таблицу, и он не обязателен: если рядом с таблицей есть подробное объяснение, можно обойтись без него. Но у таблицы с несколькими столбцами, которую читают отдельно от текста, он нужен.
Если ничего не задавать, браузер выводит заголовок по центру над таблицей, обычным шрифтом, а не жирным. Его ширина равна ширине таблицы, отступов нет. Всё это меняется в CSS, сейчас покажу как.
У соседних тегов свои задачи. Для группы полей формы заголовок пишут тегом legend, а не caption: caption подходит только для таблицы. Заголовок к иллюстрации или к таблице внутри figure задаёт тег figcaption.
| Тег | Что описывает | Пример записи |
|---|---|---|
caption | Заголовок таблицы | <table><caption>Цены</caption>...</table> |
figcaption | Пояснение к блоку внутри figure | <figure>...<figcaption>Таблица 1</figcaption></figure> |
legend | Заголовок группы полей формы | <fieldset><legend>Доставка</legend>...</fieldset> |
label | Надпись к одному полю формы | <label for="qty">Число</label> |
h3 | Заголовок раздела страницы, с таблицей не связан | <h3>Цены</h3><table>...</table> |
Где записывать тег caption: позиция в коде и на экране
Стандарт требует, чтобы caption был первым дочерним элементом table. Но браузер прощает многие ошибки, и полезно знать, что из этого получается. Главное: заголовок всегда выводится сверху или снизу, где бы он ни был записан.
| Как записан | Что получается на экране | Пример записи |
|---|---|---|
Первым в table | Заголовок над таблицей | <table><caption>Цены</caption><tr>... |
| После строк | Заголовок всё равно сверху, но код читать труднее | <table><tr>...</tr><caption>Цены</caption> |
| Два заголовка | Выводятся оба, друг под другом | <caption>Цены</caption><caption>Осень</caption> |
Вне table | Браузер отбрасывает тег, слово остаётся обычным текстом | <caption>Цены</caption><table>... |
Внутри td | Браузер выносит заголовок из ячейки к таблице | <td>Чай<caption>Цены</caption></td> |
Закрывающий тег стандарт разрешает опустить, если сразу за ним нет пробела или комментария. Например, браузер сам закрывает заголовок, когда встречает tr. Но лучше писать </caption> всегда: как только появится пробел или комментарий, короткая запись перестанет работать. Подробности - в описании элемента в стандарте HTML.
Пример: что получается при разном порядке записи
Выберите вариант записи: сверху виден код, ниже - результат.
Если заголовок добавляется скриптом, пригодятся свойство caption и два метода таблицы: createCaption() и deleteCaption(). Первый метод создаёт заголовок первым в таблице, а если заголовок уже есть, возвращает его. Второй метод убирает заголовок.
const table = document.querySelector('table');
const cap = table.createCaption();
cap.textContent = 'Цены на чай';
table.deleteCaption();
Атрибуты тега caption: align устарел, что писать вместо него
Своих актуальных атрибутов у caption нет: работают только глобальные, такие как class, id, lang и title. В старых версиях HTML был атрибут align, но он устарел. Он до сих пор встречается в чужом коде, поэтому полезно знать, что с ним делает браузер.
| Атрибут | Что делает браузер | Чем заменить | Пример записи |
|---|---|---|---|
align="bottom" | Переносит заголовок под таблицу | caption-side: bottom | <caption align="bottom"> |
alignleft, right, center, top | По стандарту ничего не меняет: заголовок остаётся сверху и по центру | text-align у caption | <caption align="left"> |
class, id, lang, title | Работают, как у любого тега | Замена не нужна | <caption lang="en"> |
Получается, что из всех значений align действует только bottom. В новом коде вместо него пишут CSS: так понятнее, а результат тот же.
<caption align="bottom">Цены</caption>
caption {
caption-side: bottom;
}
caption-side и text-align: заголовок под таблицей и выравнивание текста
Свойство caption-side переносит заголовок над таблицей или под неё. Значений у него два: top (по умолчанию) и bottom. Значения left и right были в старой версии CSS, а в современных стандартах их нет, поэтому на них лучше не рассчитывать: заголовок остаётся сверху.
Текст заголовка по умолчанию выводится по центру. Выровнять его слева или справа можно свойством text-align, но правило нужно записывать для самого caption. Если задать text-align: left таблице или её родителю, заголовок останется по центру: у него есть собственное правило браузера, и оно перебивает наследование.
caption {
caption-side: bottom;
text-align: left;
}
Пример: положение и выравнивание заголовка
Выберите положение и выравнивание: в верхней части виден код, в нижней - результат. Жёлтая заливка у caption добавлена только в демонстрации.
Ширина, рамка и фон тега caption: что входит в таблицу, а что нет
Заголовок всегда занимает ширину таблицы. Длинный текст переносится на новые строки и таблицу не расширяет. А вот длинное слово без пробелов таблицу раздвигает: переносить его некуда. Лечит это то же правило, что и для ячеек: overflow-wrap: anywhere. Как ведёт себя ширина самой таблицы, рассказано в разделе о ширине тега table.
Рамка table идёт вокруг ячеек, а заголовок остаётся над ней. Фон table закрашивает ячейки, но не заголовок. Чтобы закрасить или обвести заголовок, оформляйте сам caption: у него работают обычные свойства блока.
| Свойство | Что делает | Пример записи |
|---|---|---|
padding | Отступ вокруг текста заголовка | caption { padding: 8px 0; } |
margin-bottom | Промежуток между заголовком и таблицей | caption { margin-bottom: 10px; } |
background | Заливка только заголовка | caption { background: #fff2c9; } |
border | Рамка вокруг заголовка | caption { border: 2px solid; } |
font-weight | Жирность: по умолчанию обычная | caption { font-weight: 700; } |
overflow-wrap | Перенос слишком длинного слова | caption { overflow-wrap: anywhere; } |
Пример: ширина, рамка и фон
Потяните ползунок, выберите текст и включите рамку с фоном. У заголовка точечный контур: по нему видно, где заголовок кончается.
Закрепление caption при прокрутке таблицы вбок
Широкую таблицу обычно помещают в блок с прокруткой: как это делается, показано в разделе о таблице на телефоне. Но у такой таблицы есть неудобство: пока читатель листает столбцы вправо, заголовок уезжает за край, и становится неясно, о чём таблица.
Поможет position: sticky вместе с left: 0: заголовок закрепится у левого края блока. Условие: закрепиться может только элемент, который по ширине меньше таблицы. По умолчанию заголовок такой же ширины, как таблица, и сдвигаться ему некуда. Поэтому задайте ему ширину, например 12em.
.wrap {
overflow-x: auto;
}
caption {
position: sticky;
left: 0;
width: 12em;
}
Пример: закрепление заголовка при прокрутке
Выберите правило, нажмите «Прокрутить вправо» и сравните: без ширины заголовок уезжает вместе с таблицей, а с шириной остаётся на виду.
Тег caption в адаптивной таблице: почему заголовок сжимается
Для телефона таблицу часто перестраивают: всем её тегам задают display: block, и ячейки выстраиваются столбиком. Заголовок при этом сжимается до ширины своего текста и разбивается на много коротких строк. То же случается, если display: block задан только тегу table, как в способе с прокруткой.
Лечится это правилом display: block для самого caption внутри такой раскладки. Но не записывайте его в обычной таблице: там заголовок становится уже таблицы и смещается.
@media (max-width: 600px) {
table, tbody, tr, td, th, caption {
display: block;
}
}
Пример: заголовок в раскладке из блоков
Переключите раскладку: во втором варианте заголовок сжимается и разбивается на строки, в третьем занимает всю ширину.
Что записать внутри caption и как скрыть заголовок от глаз
Внутри caption допустим обычный текст и теги: ссылка a, выделение strong и em, abbr, time. Можно записать даже h3 или p, но вкладывать в заголовок другую таблицу нельзя. Заголовок h3 внутри caption остаётся заголовком раздела и попадает в структуру заголовков страницы, поэтому без нужды его туда не записывают.
<caption>
Цены на <strong>чай</strong>,
<time datetime="2026-09">сентябрь</time>
</caption>
Иногда заголовок нужен только скринридеру, а глазам он лишний: рядом уже есть свой заголовок раздела. Здесь важен способ скрытия. Через display: none заголовок пропадает и для скринридера, а вынесенный за экран остаётся доступным.
| Способ | Что получает таблица | Пример записи |
|---|---|---|
Видимый caption | Название совпадает с текстом заголовка | <caption>Цены</caption> |
display: none у caption | Названия нет: заголовок исчез совсем | caption { display: none; } |
| Вынос заголовка за экран | Название сохраняется, заголовка не видно | caption { position: absolute; left: -9999px; } |
aria-label у table | Название берётся из атрибута и перебивает caption | <table aria-label="Цены на чай"> |
aria-labelledby у table | Название берётся из другого элемента, например из h3 над таблицей | <table aria-labelledby="price"> |
Есть ещё одна причина писать заголовок. Стандарт HTML называет caption, thead и th вероятными признаками таблицы данных. Если в таблице одни ячейки td, браузер или скринридер может принять её за раскладку, а не за таблицу данных. Любой из этих тегов помогает избежать такой ошибки.
Если таблица - единственное, что находится в figure, кроме figcaption, стандарт советует записать figcaption, а caption не писать. Иначе у таблицы окажутся два заголовка.
Частые ошибки с тегом caption
Вот ошибки, которые встречаются чаще всего.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
<table><tr>...</tr><caption>Цены</caption></table> | Заголовок выводится сверху, но так писать неудобно, и это нарушает порядок из стандарта | Записать caption сразу после <table> |
Два caption в одной таблице | Выводятся оба, а названием таблицы считается первый | Оставить один, второй текст вынести в абзац перед таблицей |
<caption>Цены</caption><table>...</table> | Браузер отбрасывает тег, остаётся обычный текст | Записать caption внутри table |
table { text-align: left; } | Заголовок остаётся по центру | Написать caption { text-align: left; } |
caption-side: left или <caption align="left"> | Не работает: заголовок остаётся сверху | Для выравнивания текста использовать text-align |
caption { display: block; } в обычной таблице | Заголовок становится уже таблицы и смещается | Убрать правило, оно нужно только в раскладке из блоков |
caption { display: none; } | У таблицы пропадает название | Вынести заголовок за экран или задать aria-label |
position: sticky без ширины у заголовка | Заголовок не закрепляется и уезжает при прокрутке | Задать width, например 12em |
<caption> вместо legend в форме | Для группы полей формы caption не подходит | <fieldset><legend>Доставка</legend>...</fieldset> |