Таблицы в HTML

Автор: Евгений Рыжков Дата публикации: 14.08.2010

Для чего нужен тег table

В спецификациях W3C об использовании таблиц есть следующая заметка:

Таблицы не должны использоваться для разметки HTML документов. Это может вызвать проблемы при отображении страниц не визуальными браузерами. Кроме того, при работе с графикой у пользователей может появится горизонтальная прокрутка при дизайнах рассчитанных на большие мониторы. Чтобы минимизировать такие проблемы авторы должны для разметки использовать таблицы стилей ,а не таблицы.

Повлияла ли эта заметка или что-то другое, но некоторые термин «Бестабличная верстка» поняли на столько буквально — что теперь все, включая таблицы на страницах верстаются дивами. Но это не верно. Таблицы призваны размечать табличные данные. Использование таблиц по назначению существенно улучшает доступность данных. Особенно для не визуальных браузеров. Особенно при больших объемах информации.

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

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

пример простой таблицы

Чистим таблицы

Перемены приходят медленно. Блочная верстка и использование CSS сменило табличную верстку 3-4 года назад (на самом деле все еще довольно часто встречаются табличные разметки, но не будем об этом). Но все еще встречаю такие опусы:

<center>
<table cellpadding="1" cellpadding="2" bgcolor="#CCCCCC" width="300">
<tr>
	<td align="center" valign="middle"><b>Компания</b></td>
	<td align="center" valign="middle"><b>Сотрудников</b></td>
	<td align="center" valign="middle"><b>Основана</b></td>
</tr>
[...]

О тегах и атрибутах оформления давно пора забыть. Для этого предназначены таблицы стилей.

В данном примере выровнять таблицу по центру можно воспользовавшись выравниванием относительно родителя. Остальные атрибуты заменить аналогами из CSS. За знания CSS в награду получаем более чистый и красивый HTML код:

<div class="tableWrap">
	<table>
	<tr>
		<td class="tHead">Компания</td>
		<td class="tHead">Струдников</td>
		<td class="tHead">Основана</td>
	</tr>
[...]
.tableWrap {
	text-align: center; /* для выравнивания таблицы по центру */
}
table {
	border: 1px solid #000; /* вместо border="1" */
	margin: 100px;
	margin: 0 auto; /* для выравнивания таблицы по центру */
	text-align: left;
	width: 300px;
	border-spacing: 0; /* вместо cellspacing="0"  */
	background: #ccc; /* вместо bgcolor="#CCCCCC" */
}
.tHead {
	text-align: center; /* вместо align="center" */
	vertical-align: middle; /* вместо valign="middle" */
	font-weight: bold; /* вместо тега <b> */
}

Делаем таблицы доступными

Таблица, особенно объемная — это одна из самых громоздких конструкций в HTML. При корявой разметке, чтение большой таблицы для поисковых роботов и не визуальных браузеров может превратится в кошмар. Это предусмотрели отцы HTML и снабдили таблицы рядом полезных тегов и атрибутов.

Заголовки таблиц

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

  • визуальные браузеры даже при отключенных стилях отобразят заголовки иначе, чем данные таблицы, обычно выделяют полужирным шрифтом;
  • у тебя в наличии тег, который можно оформить по другому не прибегая к дополнительным классам;
  • голосовые браузеры во-первых выделят заголовки интонацией, во-вторых не дадут пользователю потеряться в таблице, т.к. каждая ячейка будет озвучена парой значений: заголовок столбца -< текущее значение.

Для примера, возьмем нашу таблицу с самой простой разметкой:

<table>
<tr>
	<td>Компания</td>
	<td>Сотрудников</td>
	<td>Основана</td>
</tr>
<tr>
	<td>Google</td>
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<td>Яндекс</td>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

Голосовой браузер прочитает это так: Компания Сотрудников Основана Google 19 665 1997 Яндекс 2000 1997. Если бы я такое услышал — мало что понял бы. Изменим на более грамотную разметку:

<table>
<tr>
	<th>Компания</th>
	<th>Сотрудников</th>
	<th>Основана</th>
</tr>
<tr>
	<td>Google</td>
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<td>Яндекс</td>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

Теперь пользователь услышит от браузера более понятную речь: Компания Google, Сотрудников 19 655, Основана 1997, Компания Яндекс, Сотрудников 2000, Основана 1997.

Сокращение заголовков

Из предыдущего примера видно, что при наличии заголовков таблицы, голосовой браузер будет сначала говорить заголовок ячейки, потом значение. Хорошо, когда заголовки короткие. А если бы были такие: Претендент на звание «лучшая компания», Численность сотрудников, В каком году основана? Голосовой браузер для каждой строки произносил заголовки столбцов. Думаю где-то на 5-й строке я бы застрелился.

Возможность суицида тоже была предусмотрена и для таких случаев спасением является атрибут abbr.

<table>
<tr>
	<th abbr="компания">Претендент на звание «лучшая компания»</th>
	<th abbr="Сотрудников">Численность сотрудников</th>
	<th abbr="Основана">В каком году основана</th>
</tr>
<tr>
	<td>Google</td>
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<td>Яндекс</td>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

При такой разметке голосовой браузер только первую строку прочитает с полными заголовками, чтобы пользователь понял о чем речь, а все последующие будет произносить в сокращенном виде (содержимое атрибутов abbr): Претендент на звание «лучшая компания» Google, Численность сотрудников 19 665, В каком году основана 1997, компания Яндекс, Сотрудников 2000, Основана 1997.

Двойные заголовки

Усложним немного нашу таблицу и снабдим ее заголовками не только для столбцов, но и для строк:

пример таблицы с заголовками и по столбцам, и по строкам
<table>
<tr>
	<td></td>
	<th>Сотрудников</th>
	<th>Основана</th>
</tr>
<tr>
	<th>Google</th>
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<th>Яндекс</th>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

Лучший способ сообщить об этом не визуальным браузерам — воспользоваться атрибутом scope:

<table>
<tr>
	<td></td> <!-- тут именно td нужно использовать -->
	<th scope="col">Сотрудников</th>
	<th scope="col">Основана</th>
</tr>
<tr>
	<th scope="row">Google</th>
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<th scope="row">Яндекс</th>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

Такая разметка позволит голосовым браузерам определять, что первая колонка — это заголовки. И по этим заголовкам можно быстро находить нужную строку и/или повторять этот заголовок перед значением каждой ячейки строки.

Если же, нужно оставить первой ячейкой заголовок (там, где раньше была компания), тогда более правильной будет такая разметка:

<table>
<tr>
	<th>Компания</th>
	<th scope="col">Сотрудников</th>
	<th scope="col">Основана</th>
</tr>
<tr>
	<td scope="row">Google</td> <!--тут уже нужно td -->
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<td scope="row">Яндекс</td>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

Т.е. делаем так, чтобы по вертикали и горизонтали <th> не пересекались, иначе синтезаторы речи с ума сойдут.

id и headers — альтернатива scope

Для связи заголовки-данные ячеек таблиц, можно использовать атрибут id, для указания заголовков (должен быть уникальным) и атрибут headers, для ячеек таблиц, чтобы перечислить связанные с этой ячейкой заголовки:

<table>
<tr>
	<td></td>
	<th id="employee">Сотрудников</th>
	<th id="found">Основана</th>
</tr>
<tr>
	<th id="google">Google</th>
	<td headers="google employee">19 665</td>
	<td headers="google found">1997</td>
</tr>
<tr>
	<th id="yandex">Яндекс</th>
	<td headers="yandex employee">2000</td>
	<td headers="yandex found">1997</td>
</tr>
</table>

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

Caption — название таблицы

Или описание. Кому как больше нравится. В общем снабжаем пользователя пояснением, что за таблица перед ним. <caption> должен идти сразу после тега <table>. Отображаться может с любой из сторон таблицы — смотря какие атрибуты ему задашь.

<table>
<caption>Факты о веб гигантах</caption>
<tr>
	<th>Компания</th>
	<th scope="col">Сотрудников</th>
	<th scope="col">Основана</th>
</tr>
<tr>
	<td scope="row">Google</td> <!--тут уже нужно td -->
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<td scope="row">Яндекс</td>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

Пояснения к таблице — summary

Зрячий человек способен быстро окинуть взглядом таблицу в считанные мгновения получить полное представление о таблице: какие данные содержит таблица, объем таблицы, сколько столбцов и т.д. Для незрячих это проблематично. Атрибут summary может предоставить более развернутую информацию о таблице, нежели <caption>. Такой шаг оценят пользователи с ограниченными возможностями и поисковые роботы. Визуальные браузеры содержимого этого атрибута не отобразят.

<table summary="Данные о лидерах веб индустрии: численность компаний, в каком году были основаны.">
<caption>Факты о веб гигантах</caption>
<tr>
	<th>Компания</th>
	<th scope="col">Сотрудников</th>
	<th scope="col">Основана</th>
</tr>
<tr>
	<td scope="row">Google</td> <!--тут уже нужно td -->
	<td>19 665</td>
	<td>1997</td>
</tr>
<tr>
	<td scope="row">Яндекс</td>
	<td>2000</td>
	<td>1997</td>
</tr>
</table>

Группируем строки: <thead>, <tfoot> и <tbody>

Стоки таблицы могут быть объединены в секции <thead>, <tfoot> и несколько <tbody>. <thead> и <tfoot> предназначены для описания содержимого таблицы, <tbody> — это само содержимое. Рекомендации:

  • каждая из этих секций должна находится внутри тега <table> и содержать минимум одну строку (<tr>);
  • <tbody> стоит использовать всегда. Пропустить этот тег можно только, если все тело таблицы является ее содержимым и отсутствуют <thead> и <tfoot>;
  • <thead> и <tfoot> должны идти до <tbody> чтобы пользовательские агенты могли получить информации о таблице до прочтения ее содержимого.
<table>
	<thead>
		<tr>...</tr>
		[...]
	</thead>
	<tfoot>
		<tr>...</tr>
		[...]
	</tfoot>
	<tbody>
		<tr>...</tr>
		[...]
	</tbody>
	<tbody>
		<tr>...</tr>
		[...]
	</tbody>
</table>

Группирование строк имеет несколько преимуществ:

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

Группируем столбцы: colgroup и col

Считаешь, что какой-то столбец особенный и требует особого внимания — <colgroup> или <col> как раз то, что нужно (теги практически идентичны по действию и назначению). К тому же эти теги помогут оформить по особому сгруппированный столбец (правда некоторые браузеры могут проигнорировать наличие этого тега).

Заключение

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

Да и для обычных пользователей от правильно сверстанной таблицы есть польза: ведь так используется меньше HTML кода и таблица весит меньше. А программистам проще с такой работать.

Материалы