Фиксированные заголовки таблиц

Тренажер по HTML для пользователей с начальным уровнем подготовки.

Тренажер HTML
Тема: фиксированные заголовки таблиц. В реальных интерфейсах длинные таблицы чаще всего прокручиваются внутри контейнера, но их заголовки (шапка) остаются на месте, чтобы пользователь всегда видел названия колонок. Это достигается сочетанием правильной HTML‑структуры (thead/tbody/tfoot, th вместо td для заголовков, атрибуты scope) и готового CSS со свойством position: sticky и координатами top/bottom. В заданиях вы будете собирать таблицы с прокручиваемым контейнером, размечать шапку и подвал, добавлять семантику для доступности, делать фиксированной первую колонку и создавать многоуровневые заголовки. Каждое упражнение снабжено готовым CSS, а в HTML есть пропуски inputN — вам нужно заполнить их корректными тегами, именами атрибутов и значениями, чтобы шапка таблицы фиксировалась и работала в iframe. Никакой теории и догадок о данных: все тексты, числа и подписи уже в коде — вы концентрируетесь на синтаксисе и разметке.
Список тем

Базовая таблица с фиксированной шапкой

id: 37840_fixed-header-basic

Соберите таблицу с прокручиваемым контейнером и фиксированной шапкой. Заголовок с названиями колонок должен оставаться на месте при вертикальной прокрутке, а строки таблицы прокручиваться внутри рамки. Структура должна включать отдельный раздел для заголовков и раздел для данных.

CSS
*, *::before, *::after { box-sizing: border-box; }
.tbl-wrap { max-height: 220px; overflow: auto; border: 1px solid #e0e0e0; border-radius: 6px; }
.tbl { width: 100%; border-collapse: collapse; font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }
.tbl thead th { position: sticky; top: 0; background: #ffffff; z-index: 2; }
.tbl th, .tbl td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.tbl thead th { border-bottom: 1px solid #ccc; }
HTML
<div class="input1">
  <input2 class="input3">
    <input4>
      <input5>
        <input6>Товар</input6>
        <input6>Цена</input6>
        <input6>Кол-во</input6>
        <input6>Итого</input6>
      </input5>
    </input4>
    <input7>
      <tr>
        <td>Кофе</td>
        <td>350 ₽</td>
        <td>2</td>
        <td>700 ₽</td>
      </tr>
      <tr>
        <td>Чай</td>
        <td>180 ₽</td>
        <td>3</td>
        <td>540 ₽</td>
      </tr>
      <tr>
        <td>Сок</td>
        <td>120 ₽</td>
        <td>4</td>
        <td>480 ₽</td>
      </tr>
      <tr>
        <td>Вода</td>
        <td>70 ₽</td>
        <td>5</td>
        <td>350 ₽</td>
      </tr>
      <tr>
        <td>Молоко</td>
        <td>95 ₽</td>
        <td>2</td>
        <td>190 ₽</td>
      </tr>
      <tr>
        <td>Какао</td>
        <td>210 ₽</td>
        <td>1</td>
        <td>210 ₽</td>
      </tr>
      <tr>
        <td>Лимонад</td>
        <td>130 ₽</td>
        <td>3</td>
        <td>390 ₽</td>
      </tr>
      <tr>
        <td>Квас</td>
        <td>115 ₽</td>
        <td>2</td>
        <td>230 ₽</td>
      </tr>
    </input7>
  </input2>
</div>
Нужен контейнер с overflow для прокрутки и таблица с корректной структурой. Используйте div с классом "tbl-wrap" как прокручиваемую обёртку и table с классом "tbl". Заголовки должны быть th внутри thead, строки заголовков — tr. Данные поместите в tbody. Готовый CSS закрепит thead th через position: sticky.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Добавьте атрибуты scope для колонок

id: 37840_fixed-header-scope-cols

Семантически опишите заголовки колонок так, чтобы они были корректно интерпретированы технологиями доступности. Шапка остаётся фиксированной при прокрутке, а каждая заголовочная ячейка должна явно указывать, что относится к столбцу.

CSS
.tbl-wrap { max-height: 220px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.tbl { width: 100%; border-collapse: collapse; }
.tbl thead th { position: sticky; top: 0; background: #fff; z-index: 2; }
.tbl th, .tbl td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.tbl thead th { border-bottom: 1px solid #ccc; }
HTML
<div class="tbl-wrap">
  <table class="tbl">
    <thead>
      <tr>
        <th input1="input2">Товар</th>
        <th input3="input4">Цена</th>
        <th input5="input6">Кол-во</th>
        <th input7="input8">Итого</th>
      </tr>
    </thead>
    <tbody>
      <tr><td>Кофе</td><td>350 ₽</td><td>2</td><td>700 ₽</td></tr>
      <tr><td>Чай</td><td>180 ₽</td><td>3</td><td>540 ₽</td></tr>
      <tr><td>Сок</td><td>120 ₽</td><td>4</td><td>480 ₽</td></tr>
      <tr><td>Вода</td><td>70 ₽</td><td>5</td><td>350 ₽</td></tr>
    </tbody>
  </table>
</div>
Устанавливайте атрибут scope на заголовках в thead. Для заголовков столбцов используйте значение col. Пример для одной ячейки: <th scope="col">...<\/th>. Примените это ко всем ячейкам заголовка.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Перенесите заголовки в отдельный thead

id: 37840_fixed-header-add-thead

Приведите разметку к правильной структуре таблицы: заголовки должны быть отделены в специальную секцию, а данные — в свою. После исправления шапка должна фиксироваться при прокрутке благодаря готовому стилю.

CSS
.scrollarea { max-height: 230px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.data-table { width: 100%; border-collapse: collapse; }
.data-table thead th { position: sticky; top: 0; background: #fff; z-index: 2; }
.data-table th, .data-table td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; }
.data-table thead th { border-bottom: 1px solid #ccc; text-align: left; }
HTML
<div class="scrollarea">
  <table class="data-table">
    <input1>
      <tr>
        <input2>Город</input2>
        <input2>Население</input2>
      </tr>
    </input1>
    <input3>
      <tr><td>Москва</td><td>13 104 177</td></tr>
      <tr><td>Санкт-Петербург</td><td>5 603 797</td></tr>
      <tr><td>Новосибирск</td><td>1 635 364</td></tr>
      <tr><td>Екатеринбург</td><td>1 550 425</td></tr>
      <tr><td>Казань</td><td>1 308 660</td></tr>
      <tr><td>Нижний Новгород</td><td>1 222 796</td></tr>
    </input3>
  </table>
</div>
Заголовочная часть должна быть внутри thead, строки заголовков — tr, ячейки заголовка — th. Данные разместите в tbody. Готовый CSS применяет position: sticky к thead th.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Сделайте левый столбец фиксированным

id: 37840_fixed-header-sticky-first-col

Кроме зафиксированной шапки закрепите также первый столбец с названиями элементов. Он должен оставаться видимым при горизонтальной и вертикальной прокрутке контейнера.

CSS
.scroll { max-height: 240px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.tbl { width: 100%; border-collapse: collapse; min-width: 480px; }
.tbl th, .tbl td { padding: 8px; border-bottom: 1px solid #eee; font-size: 14px; }
.tbl thead th { position: sticky; top: 0; background: #fff; z-index: 3; text-align: left; }
.tbl tbody th[scope="row"] { position: sticky; left: 0; background: #fff; z-index: 2; text-align: left; }
HTML
<div class="scroll">
  <table class="tbl">
    <thead>
      <tr>
        <th>Код</th>
        <th>Наименование</th>
        <th>Остаток</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <input1 input2="input3">A101</input1>
        <td>Смартфон</td>
        <td>56</td>
      </tr>
      <tr>
        <input4 input5="input6">B205</input4>
        <td>Наушники</td>
        <td>120</td>
      </tr>
      <tr>
        <input7 input8="input9">C309</input7>
        <td>Зарядное устройство</td>
        <td>78</td>
      </tr>
    </tbody>
  </table>
</div>
Чтобы закрепить первый столбец, используйте заголовочные ячейки в строках данных: th с атрибутом scope="row". Готовый CSS делает thead th фиксированными сверху и tbody th[scope=row] фиксированными слева.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Фиксированная шапка через класс

id: 37840_fixed-header-class-based

Сделайте шапку фиксированной не по селектору элемента, а с помощью специального класса. Класс должен быть назначен нужной секции, чтобы заголовки оставались видимыми при прокрутке.

CSS
.table-scroll { max-height: 220px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.data { width: 100%; border-collapse: collapse; }
.data thead.sticky-top th { position: sticky; top: 0; background: #fff; z-index: 2; }
.data th, .data td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.data thead th { border-bottom: 1px solid #ccc; }
HTML
<div class="table-scroll">
  <table class="data">
    <input1 input2="input3">
      <tr>
        <th>Дата</th>
        <th>Доход</th>
        <th>Расход</th>
      </tr>
    </input1>
    <tbody>
      <tr><td>01.09</td><td>12 000 ₽</td><td>8 500 ₽</td></tr>
      <tr><td>02.09</td><td>15 300 ₽</td><td>9 200 ₽</td></tr>
      <tr><td>03.09</td><td>11 800 ₽</td><td>7 900 ₽</td></tr>
      <tr><td>04.09</td><td>14 050 ₽</td><td>9 100 ₽</td></tr>
      <tr><td>05.09</td><td>13 500 ₽</td><td>8 750 ₽</td></tr>
    </tbody>
  </table>
</div>
Добавьте класс на секцию заголовка и используйте готовый стиль. В этом задании фиксируется именно thead с классом "sticky-top". Не забудьте использовать корректный атрибут для назначения класса.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Правильная обёртка для прокрутки

id: 37840_fixed-header-wrapper

Сделайте так, чтобы таблица прокручивалась внутри собственного контейнера с рамкой, а заголовок оставался на месте. Контейнер должен иметь соответствующий класс для применения стилей прокрутки.

CSS
.cont { max-height: 200px; overflow: auto; border: 1px solid #dcdcdc; border-radius: 6px; }
.tbl { width: 100%; border-collapse: collapse; }
.tbl thead th { position: sticky; top: 0; background: #fff; z-index: 2; }
.tbl th, .tbl td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.tbl thead th { border-bottom: 1px solid #ccc; }
HTML
<input1 class="input2">
  <table class="tbl">
    <thead>
      <tr>
        <th>Клиент</th>
        <th>Счёт</th>
        <th>Статус</th>
      </tr>
    </thead>
    <tbody>
      <tr><td>ООО "Вектор"</td><td>№ 541</td><td>Оплачен</td></tr>
      <tr><td>ИП "Лес"</td><td>№ 542</td><td>Ожидает</td></tr>
      <tr><td>ООО "Техно"</td><td>№ 543</td><td>Оплачен</td></tr>
      <tr><td>ООО "Лайт"</td><td>№ 544</td><td>Просрочен</td></tr>
      <tr><td>ООО "Контур"</td><td>№ 545</td><td>Оплачен</td></tr>
      <tr><td>ИП "Сфера"</td><td>№ 546</td><td>Ожидает</td></tr>
    </tbody>
  </table>
</input1>
Используйте обёртку div с классом "cont" для ограничения высоты и включения overflow: auto. Таблица остаётся обычной с разделением thead/tbody. Готовый CSS по классу .cont управляет прокруткой.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Двухуровневая фиксированная шапка

id: 37840_fixed-header-multiline-header

Создайте многоуровневую шапку из двух строк: верхняя строка объединяет колонки в группы, нижняя — содержит конкретные заголовки. Обе строки должны оставаться на месте при прокрутке.

CSS
.wrap { max-height: 230px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.tbl { width: 100%; border-collapse: collapse; }
.tbl th, .tbl td { padding: 8px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.tbl thead tr:nth-child(1) th { position: sticky; top: 0; background: #fff; z-index: 3; }
.tbl thead tr:nth-child(2) th { position: sticky; top: 32px; background: #fff; z-index: 2; }
HTML
<div class="wrap">
  <table class="tbl">
    <input1>
      <input2>
        <th colspan="2">Продажи</th>
        <th colspan="2">Склад</th>
      </input2>
      <input3>
        <th>Город</th>
        <th>Сумма</th>
        <th>Доступно</th>
        <th>Ожидается</th>
      </input3>
    </input1>
    <tbody>
      <tr><td>Москва</td><td>1 200 000 ₽</td><td>540</td><td>120</td></tr>
      <tr><td>Казань</td><td>320 000 ₽</td><td>210</td><td>60</td></tr>
      <tr><td>Пермь</td><td>210 000 ₽</td><td>130</td><td>20</td></tr>
      <tr><td>Тверь</td><td>95 000 ₽</td><td>70</td><td>10</td></tr>
    </tbody>
  </table>
</div>
Нужны два tr внутри thead. CSS уже задаёт разные top для первой и второй строк: первая прилипает к верху, вторая располагается прямо под первой. Верхний ряд использует colspan для объединения колонок.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Групповые заголовки с корректным scope

id: 37840_fixed-header-scope-colgroup

Добавьте атрибуты для обозначения групп колонок и конкретных колонок. Это улучшает доступность и навигацию по таблице. Шапка остаётся фиксированной для обеих строк заголовков.

CSS
.wrap2 { max-height: 230px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.tbl2 { width: 100%; border-collapse: collapse; }
.tbl2 th, .tbl2 td { padding: 8px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.tbl2 thead tr:nth-child(1) th { position: sticky; top: 0; background: #fff; z-index: 3; }
.tbl2 thead tr:nth-child(2) th { position: sticky; top: 32px; background: #fff; z-index: 2; }
HTML
<div class="wrap2">
  <table class="tbl2">
    <thead>
      <tr>
        <th input1="input2" colspan="2">Продажи</th>
        <th input3="input4" colspan="2">Склад</th>
      </tr>
      <tr>
        <th input5="input6">Город</th>
        <th input7="input8">Сумма</th>
        <th input9="input10">Доступно</th>
        <th input11="input12">Ожидается</th>
      </tr>
    </thead>
    <tbody>
      <tr><td>Москва</td><td>1 200 000 ₽</td><td>540</td><td>120</td></tr>
      <tr><td>Казань</td><td>320 000 ₽</td><td>210</td><td>60</td></tr>
      <tr><td>Тверь</td><td>95 000 ₽</td><td>70</td><td>10</td></tr>
    </tbody>
  </table>
</div>
У верхних заголовков используйте scope="colgroup" и задайте colspan. У нижних — scope="col". Так технологии чтения поймут, что верхний уровень — группа колонок, а нижний — конкретные колонки.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Горизонтальная прокрутка и фиксированная шапка

id: 37840_fixed-header-horizontal-scroll

Соберите широкую таблицу, которая выходит за пределы видимой области по ширине. Внутренний скролл должен быть горизонтальным и вертикальным, а шапка оставаться закреплённой сверху при прокрутке.

CSS
.hscroll { max-height: 220px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.wide { border-collapse: collapse; min-width: 720px; width: 100%; }
.wide th, .wide td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; white-space: nowrap; }
.wide thead th { position: sticky; top: 0; background: #fff; z-index: 2; border-bottom: 1px solid #ccc; }
HTML
<input1 class="input2">
  <input3 class="input4">
    <thead>
      <tr>
        <th>Товар</th>
        <th>Категория</th>
        <th>Поставщик</th>
        <th>Цена</th>
        <th>Скидка</th>
        <th>Наличие</th>
        <th>Артикул</th>
      </tr>
    </thead>
    <tbody>
      <tr><td>Смартфон</td><td>Электроника</td><td>ООО "Мобайл"</td><td>29 990 ₽</td><td>5%</td><td>Да</td><td>SP-001</td></tr>
      <tr><td>Планшет</td><td>Электроника</td><td>ООО "ТехноМаркет"</td><td>19 990 ₽</td><td>10%</td><td>Да</td><td>TB-210</td></tr>
      <tr><td>Монитор</td><td>Периферия</td><td>ООО "Вижн"</td><td>17 900 ₽</td><td>0%</td><td>Нет</td><td>MN-432</td></tr>
      <tr><td>Клавиатура</td><td>Периферия</td><td>ИП "Клаво"</td><td>3 200 ₽</td><td>15%</td><td>Да</td><td>KB-998</td></tr>
    </tbody>
  </input3>
</input1>
Используйте обёртку с классом для прокрутки по обеим осям и таблицу с минимальной шириной больше контейнера. Назначьте классы из готового CSS: у обёртки — "hscroll", у таблицы — "wide".
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Добавьте подвал таблицы (tfoot) и закрепите его

id: 37840_fixed-header-sticky-footer

К таблице с фиксированной шапкой добавьте подвал с итого-строкой, который будет прикреплён к нижней границе прокручиваемой области. При прокрутке вниз подвал должен оставаться видимым.

Комбинация: фиксированная шапка и первая колонка

id: 37840_fixed-header-header-and-left

Сделайте таблицу, в которой одновременно фиксируются шапка и первый столбец. При прокрутке вниз и в сторону заголовки колонок и названия строк остаются видимыми.

CSS
.view { max-height: 230px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.t { width: 100%; border-collapse: collapse; min-width: 520px; }
.t th, .t td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.t thead th { position: sticky; top: 0; background: #fff; z-index: 3; }
.t tbody th[scope="row"] { position: sticky; left: 0; background: #fff; z-index: 2; }
HTML
<div class="view">
  <table class="t">
    <input1>
      <tr>
        <th>Код</th>
        <th>Товар</th>
        <th>Цена</th>
        <th>Остаток</th>
      </tr>
    </input1>
    <tbody>
      <tr>
        <input2 input3="input4">A1</input2>
        <td>Флешка 32ГБ</td>
        <td>790 ₽</td>
        <td>45</td>
      </tr>
      <tr>
        <input5 input6="input7">B2</input5>
        <td>Жёсткий диск 1ТБ</td>
        <td>4 990 ₽</td>
        <td>12</td>
      </tr>
      <tr>
        <input8 input9="input10">С3</input8>
        <td>Мышь беспроводная</td>
        <td>1 290 ₽</td>
        <td>33</td>
      </tr>
    </tbody>
  </table>
</div>
Шапка — внутри thead с th. Первый столбец в данных — th с scope="row". Контейнер должен прокручиваться. Готовый CSS закрепляет thead th (top: 0) и tbody th[scope=row] (left: 0).
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Заголовок таблицы (caption) и фиксированная шапка

id: 37840_fixed-header-caption

Добавьте подпись к таблице и убедитесь, что шапка остаётся фиксированной. Подпись должна находиться в правильном месте структуры и не влиять на работу фиксированного заголовка.

CSS
.area { max-height: 220px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.rpt { width: 100%; border-collapse: collapse; }
.rpt caption { caption-side: top; padding: 6px 8px; font-weight: 600; text-align: left; }
.rpt thead th { position: sticky; top: 0; background: #fff; z-index: 2; border-bottom: 1px solid #ccc; }
.rpt th, .rpt td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
HTML
<div class="area">
  <table class="rpt">
    <input1>Отчёт по сделкам</input1>
    <thead>
      <tr>
        <th>Менеджер</th>
        <th>Сделок</th>
        <th>Выручка</th>
      </tr>
    </thead>
    <tbody>
      <tr><td>Анна</td><td>12</td><td>1 200 000 ₽</td></tr>
      <tr><td>Игорь</td><td>9</td><td>830 000 ₽</td></tr>
      <tr><td>Светлана</td><td>15</td><td>1 450 000 ₽</td></tr>
      <tr><td>Михаил</td><td>7</td><td>610 000 ₽</td></tr>
    </tbody>
  </table>
</div>
Используйте элемент caption сразу после открытия table. Заголовки колонок оформите в thead с th, данные — в tbody. Готовый CSS фиксирует thead th.
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку

Комбо: шапка, первая колонка и подвал

id: 37840_fixed-header-combo

Соберите таблицу с одновременно фиксированной шапкой, левой колонкой и подвалом. При прокрутке вниз шапка остаётся сверху, первая колонка — слева, а итоговая строка — у нижней границы.

CSS
.container { max-height: 240px; overflow: auto; border: 1px solid #ddd; border-radius: 6px; }
.table { width: 100%; border-collapse: collapse; min-width: 520px; }
.table th, .table td { padding: 8px 10px; border-bottom: 1px solid #eee; font-size: 14px; text-align: left; }
.table thead th { position: sticky; top: 0; background: #fff; z-index: 3; border-bottom: 1px solid #ccc; }
.table tbody th[scope="row"] { position: sticky; left: 0; background: #fff; z-index: 2; }
.table tfoot th { position: sticky; bottom: 0; background: #fff; z-index: 3; border-top: 1px solid #ccc; }
HTML
<div class="container">
  <table class="table">
    <input1>
      <tr>
        <th>Код</th>
        <th>Товар</th>
        <th>Цена</th>
        <th>Кол-во</th>
        <th>Итого</th>
      </tr>
    </input1>
    <tbody>
      <tr>
        <input2 input3="input4">A1</input2>
        <td>Флешка 32ГБ</td>
        <td>790 ₽</td>
        <td>2</td>
        <td>1 580 ₽</td>
      </tr>
      <tr>
        <input5 input6="input7">B2</input5>
        <td>Жёсткий диск 1ТБ</td>
        <td>4 990 ₽</td>
        <td>1</td>
        <td>4 990 ₽</td>
      </tr>
      <tr>
        <input8 input9="input10">C3</input8>
        <td>Мышь беспроводная</td>
        <td>1 290 ₽</td>
        <td>3</td>
        <td>3 870 ₽</td>
      </tr>
    </tbody>
    <input11>
      <tr>
        <input12 colspan="4">Итого</input12>
        <th>10 440 ₽</th>
      </tr>
    </input11>
  </table>
</div>
Используйте thead с th для шапки, tbody с th scope="row" для первой колонки, tfoot для итога. Готовые стили фиксируют: thead th (top: 0), tbody th[scope=row] (left: 0), tfoot th (bottom: 0).
Заполнить ответами все поля
Результат
Сообщения
Выполнить
Показать подсказку
НайтиКурс.Ру