HTML и работа с таблицами: теги, объединение ячеек, стилизация

HTML и работа с таблицами: теги, объединение ячеек, стилизация Полезное

HTML-таблица — это способ вывести данные строками и столбцами с помощью тега <table> и вложенных в него строк <tr> и ячеек <td> (данные) или <th> (заголовки). Таблица нужна именно для табличных данных — расписаний, прайсов, сравнений, — а не для верстки макета страницы: раскладку страницы делают через CSS (flexbox, grid).

Ниже — минимальный рабочий пример, затем разбор каждого тега, объединение ячеек через colspan/rowspan, доступность для скринридеров и стилизация через CSS. Сквозной пример один — прайс на смартфоны.

Минимальная таблица целиком

Начнем с законченного примера, который можно скопировать в .html-файл и открыть в браузере. Тег <table> — контейнер всей таблицы, <tr> (table row) задает строку, <td> (table data) — ячейку с данными.

<table>
  <tr>
    <td>iPhone 15</td>
    <td>80000</td>
  </tr>
  <tr>
    <td>Xiaomi 14</td>
    <td>65000</td>
  </tr>
</table>

В браузере это две строки по две ячейки: слева модель, справа цена. Столбцов отдельного тега нет — колонка возникает из того, что во всех строках ячейки идут в одном порядке. Поэтому число ячеек в строках держат одинаковым, иначе таблица «поедет».

Важно различать роли: <tr> задает строку, а колонку никакой тег не создает напрямую — она складывается из ячеек на одной позиции во всех строках.

Заголовки ячеек: th вместо td

Первая строка тут — обычные данные, а не заголовки. Для заголовка столбца или строки есть отдельный тег <th> (table header). Браузер по умолчанию делает текст в <th> жирным и центрирует его, но главное — не оформление, а смысл: <th> помечает ячейку как заголовок.

<table>
  <tr>
    <th>Модель</th>
    <th>Цена, руб</th>
  </tr>
  <tr>
    <td>iPhone 15</td>
    <td>80000</td>
  </tr>
</table>

Разница <td> и <th> не косметическая: скринридер объявляет <th> как заголовок и связывает его с ячейками данных, поэтому подписи колонок и строк всегда делают через <th>, а не через <td> с жирным шрифтом.

Структурные секции: thead, tbody, tfoot, caption

Кроме строк и ячеек у таблицы есть секции, которые группируют строки по смыслу. Они не рисуют новых ячеек — они делят таблицу на шапку, тело и итог, чтобы разметка читалась и корректно обрабатывалась.

  • <thead> — шапка со строками заголовков;
  • <tbody> — основное тело с данными (их может быть несколько — под разные смысловые блоки);
  • <tfoot> — строка итогов («подвал»);
  • <caption> — подпись-название всей таблицы, ставится сразу после <table>.
<table>
  <caption>Цены на флагманы, сентябрь 2026</caption>
  <thead>
    <tr>
      <th scope="col">Модель</th>
      <th scope="col">Цена, руб</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">iPhone 15</th>
      <td>80000</td>
    </tr>
    <tr>
      <th scope="row">Xiaomi 14</th>
      <td>65000</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th scope="row">Средняя цена</th>
      <td>72500</td>
    </tr>
  </tfoot>
</table>

По порядку в разметке <tfoot> в современном HTML ставят последним, после <tbody>. Если секции не писать вовсе, браузер сам оборачивает строки в неявный <tbody> — но явные секции полезны на сложных таблицах: они разделяют шапку, данные и итоги и помогают ассистивным технологиям.

Атрибут scope в примере — для доступности, о нем ниже.

Объединение ячеек: colspan и rowspan

Две ячейки объединяют атрибутами. Здесь легко перепутать направление: colspan растягивает ячейку по горизонтали на несколько столбцов, rowspan — по вертикали на несколько строк.

  • colspan="N" — ячейка занимает N столбцов (одна общая шапка над группой колонок);
  • rowspan="N" — ячейка занимает N строк (общий заголовок для нескольких строк подряд).

Разнесем прайс на производителя и модели: ячейка «Apple» через rowspan="2" накрывает две строки моделей.

<table>
  <thead>
    <tr>
      <th scope="col">Производитель</th>
      <th scope="col">Модель</th>
      <th scope="col">Цена, руб</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="rowgroup" rowspan="2">Apple</th>
      <td>iPhone 15</td>
      <td>80000</td>
    </tr>
    <tr>
      <td>iPhone 15 Pro</td>
      <td>110000</td>
    </tr>
    <tr>
      <th scope="rowgroup" rowspan="2">Xiaomi</th>
      <td>Xiaomi 14</td>
      <td>65000</td>
    </tr>
    <tr>
      <td>Xiaomi 14 Pro</td>
      <td>85000</td>
    </tr>
  </tbody>
</table>

Обратите внимание: в строках после объединения ячеек меньше, чем колонок. Во второй строке всего две <td>, потому что первый столбец уже занят растянутой ячейкой «Apple». Это нормально — главное, чтобы суммарная сетка сходилась. Если посчитать ячейки с учетом span и они не складываются в прямоугольник, браузер отрисует «дыры» или лишние клетки.

Для горизонтального объединения возьмем colspan — одна шапка над двумя колонками характеристик:

<tr>
  <th scope="col" rowspan="2">Модель</th>
  <th scope="colgroup" colspan="2">Характеристики</th>
</tr>
<tr>
  <th scope="col">Экран</th>
  <th scope="col">Память</th>
</tr>

По умолчанию у любой ячейки colspan и rowspan равны 1 — писать их без объединения не нужно.

Доступность таблиц

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

  • <caption> дает таблице название, которое скринридер зачитывает при входе в нее — что это за данные;
  • <th> помечает заголовки, а атрибут scope говорит, к чему заголовок относится: scope="col" — к столбцу, scope="row" — к строке, scope="colgroup"/scope="rowgroup" — к группе под colspan/rowspan;
  • заголовки строк тоже делают через <th scope="row">, а не обычным <td>.

Со scope скринридер при переходе по ячейкам называет и заголовок столбца, и заголовок строки — пользователь понимает, что «80000» относится к строке «iPhone 15» и столбцу «Цена». Для очень сложных таблиц с многоуровневой шапкой есть связка атрибутов headers (на ячейке) и id (на заголовках) — но для типичного прайса хватает scope.

Отдельно: не верстайте таблицами макет страницы. Раньше <table> использовали для колоночной раскладки — сегодня это делают через CSS (flexbox, grid), а <table> оставляют строго под табличные данные. Табличная разметка макета путает скринридеры и ломает адаптивность.

Стилизация через CSS

У таблицы нет встроенных рамок — по умолчанию ячейки без границ, и соседние рамки задваиваются. Границы, отступы и заливку задают через CSS. Ключевое свойство — border-collapse: collapse: оно схлопывает двойные рамки соседних ячеек в одну линию.

table {
  border-collapse: collapse;
  width: 100%;
}

th,
td {
  border: 1px solid #ccc;
  padding: 8px 12px;
  text-align: left;
}

thead th {
  background: #f2f2f2;
}

tbody tr:nth-child(even) {
  background: #fafafa;
}

caption {
  caption-side: top;
  font-weight: bold;
  margin-bottom: 8px;
}

Здесь border рисует линии ячеек, padding — внутренние отступы, nth-child(even) подсвечивает четные строки для читаемости. Рамку логично вешать на <th>/<td>: секции <thead>, <tbody>, <tfoot> и строки <tr> можно красить фоном, но границы ячеек управляются на уровне самих ячеек.

Адаптивность на мобильных

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

.table-wrap {
  overflow-x: auto;
}
<div class="table-wrap">
  <table>
    <!-- ... строки таблицы ... -->
  </table>
</div>

Альтернатива для очень узких экранов — перестроить таблицу в карточки через CSS (display: block на строках в media-запросе) или скрыть второстепенные колонки. Прокрутка проще и не ломает семантику, поэтому начинают обычно с нее.

Выводы

  • Таблица — это <table> со строками <tr> и ячейками <td> (данные) и <th> (заголовки); колонок отдельного тега нет, они складываются из ячеек на одной позиции.
  • Секции <thead>, <tbody>, <tfoot> и подпись <caption> группируют строки по смыслу и улучшают читаемость разметки и доступность.
  • colspan объединяет ячейки по столбцам (горизонталь), rowspan — по строкам (вертикаль); после объединения ячеек в строке меньше, но сетка должна сходиться в прямоугольник.
  • Доступность держится на трех приемах: <caption>, заголовки через <th> и атрибут scope (col/row/colgroup/rowgroup).
  • Границ по умолчанию нет — их и остальное оформление задают через CSS (border-collapse, border, padding); таблицы только для данных, макет — через flexbox/grid.

Где применяется / связь с практикой

Таблицы — базовый навык верстки: прайсы, спецификации товаров, расписания, сравнительные блоки в статьях. На реальных проектах к ним сразу добавляются CSS-оформление и адаптивность, а семантика и доступность — требование, которое проверяют на код-ревью.

Освойте тему на практике

Собрать это в цельный навык верстки помогает курс HTML/CSS — он идет первой ступенью FullStack-направления и разбирает разметку и стилизацию на практике. Посмотреть формат и темы вживую можно на открытых уроках до записи на курс.

Смежные темы: Введение в основы HTML для новичков, Работа с изображениями HTML через CSS.

FAQ

Можно ли сделать таблицу без tbody и thead?
Да. Если написать только <tr> с <td> внутри <table>, браузер сам обернет строки в неявный <tbody>, и таблица отобразится. Явные секции нужны для читаемости разметки, стилизации и доступности, а не для того, чтобы таблица заработала.

Чем colspan отличается от rowspan?
colspan растягивает ячейку по горизонтали на несколько столбцов, rowspan — по вертикали на несколько строк. Мнемоника: col — column (столбец), row — строка. Оба по умолчанию равны 1.

Почему таблица без CSS показывается без рамок?
У элемента <table> нет встроенных границ ячеек. Их добавляют через CSS: свойство border на <th>/<td> плюс border-collapse: collapse на <table>, чтобы рамки соседних ячеек не задваивались.

OTUS Журнал