Семантическая вёрстка. Часть первая

Современный взгляд на организацию кода. По материалам доклада «Семантическая вёрстка» на конференциях ClientSide 2007 и UA Web 2008.

Начало. Продолжение — «Семантическая вёрстка. Часть вторая».

Прежде всего, давайте договоримся: семантическая вёрстка — это не гербалайф. Она не поможет вам в одночасье научиться верстать в восемь раз быстрее, IE6 вдруг не перестанет бажить, да и волосы не станут гладкими и шелковистыми, скорее наоборот. Более того, использование данного подхода потребует от вас бóльших умственных усилий. Как на освоение методики, так и в работе с ней.

В чём же смысл? Зачем я предлагаю использовать подход, который, на первый взгляд, только усложняет жизнь? Просто поверьте — оно того стоит, но обо всём по порядку.

Семантика?

Семантика (фр. sémantique от греч. σημαντικός — обозначающий)

Понятие «семантика» пришло к нам из лингвистики в несколько сокращённом значении для того, чтобы можно было применить его к HTML-вёрстке. Прежде всего, семантика в вёрстке — это совокупность смысловых отношений, возникающих в документе. Однако для существования таких отношений необходим документ, который возникает благодаря внедрению HTML-разметки в простой текст.

Сайт, страница, документ

Для более уверенного разговора на эту тему, будет полезно договориться о терминах:

Таким образом, для разговора о семантике нам необходим валидный, семантически верно размеченный HTML-документ.

Смысловые связи

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

Семантика — совокупность смысловых отношений.

Однако мы ведём речь о семантике относительно HTML-вёрстки, поэтому разметим указанный пример при помощи элемента <dl>, предназначенного для создания списка определений (definition list).

<dl>
    <dt>Семантика</dt>
    <dd>совокупность смысловых отношений.</dd>
</dl>

Итак, перед нами термин <dt> (definition term) и его определение <dd> (definition description), которые связаны теми же смысловыми отношениями, что и означающее и означаемое в изначальном предложении.

Однако особенность нашей ситуации состоит в том, что для существования подобных связей нам не требуется осмысленного предложения. Все смысловые отношения продиктованы нам контейнером <dl>. По этой причине, текст внутри элементов <dt> и <dd> может быть абсолютно любым:

<dl>
    <dt>.........</dt>
    <dd>.................................</dd>
</dl>

Создавать логически стройный текст документа — это забота редактора, наше же дело — формировать абстрактную логику документа. Из чего следует, что семантические связи в документе существует только между HTML-элементами, а не между отдельными словами или частями текста.

Уровни семантики

Создание семантически верного документа — это не только использование HTML-элементов по назначению. Существует три уровня существования семантики в HTML-документе — от самого простого к более сложному:

Рассмотрим, в качестве примера всех трёх уровней, разметку простой информации:

Алексей Рыбаков, alex@example.com

Для начала правильно разметим информацию при помощи HTML-элементов. Озаглавим персону элементом <h3> и отметим адрес электронной почты при помощи элемента <address>:

<h3>Алексей Рыбаков</h3>
<address>alex@example.com</address>

Затем, в случае необходимости дополнительного оформления элементов, правильно назовём классы для имени (name) и электронной почты (email):

<h3 class="name">Алексей Рыбаков</h3>
<address class="email">alex@example.com</address>

И, наконец, усложним разметку при помощи микроформата hCard настолько, что строка текста превратится в полноценную визитную карточку. Корневой класс vcard, точное указание на имя (given-name), фамилию (family-name) и электронную почту (email) персоны:

<div class="vcard">
    <h3 class="fn n">
        <span class="given-name">Алексей</span>
        <span class="family-name">Рыбаков</span>
    </h3>
    <address class="email">alex@example.com</address>
</div>

А теперь рассмотрим подробнее каждый из уровней.

Первый уровень семантики: применение HTML-элементов

С чего же мы взяли, что, к примеру, элемент <h1> должен быть заголовком первого уровня, а <ul> неупорядоченным списком? Информация о всех элементах той версии языка, с которой вы работаете, содержится в DTD (Document Type Definition), либо в спецификации соответствующей версии.

Перед вами фрагмент DTD спецификации HTML 4.01:

<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
<!--
There are six levels of headings from H1 (the most important)
to H6 (the least important).
-->
<!ELEMENT (%heading;) - - (%inline;)* -- heading -->
<!ATTLIST (%heading;)
%attrs; -- %coreattrs, %i18n, %events --
>

Обратите внимание на комментарий:

Существуют шесть уровней заголовков: от H1 (самого значимого) до H6 (наименее значимого).

Таким образом, получается, что все особенности применения элемента и смысловые связи, которые образует с остальными элементами, расписаны в спецификации, остаётся только научиться использовать эту информацию. Конечно, такие подробности удобнее всего выяснять в полной спецификации, но наличие ссылки на DTD в <DOCTYPE> вашего документа, теперь становится ещё более очевидным.

Подобное использование HTML-элементов по их назначению, получило название POSH (Plain Old Semantic HTML) — проще говоря, «старый добрый семантический HTML».

Рассмотрим пример типичной «дивной» вёрстки:

<div id="menu">
    <a href="#">Колбаса</a>
    <br/>
    <a href="#">Макароны</a>
    <br/>
    <a href="#">Тушёнка</a>
</div>

Формально, такой код подходит популярному нынче требованию «дивной» или «бестабличной» вёрстки. Таблиц нет, див есть и даже внятно именован, код вполне может нормально отображаться во всех браузерах. Чего же боле?

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

Исходя из увиденного, практически не остаётся сомнений, каким образом разметить эту информацию: неупорядоченный список <ul> c элементами списка <li> внутри, а визуальное форматирование — в CSS.

<ul id="menu">
    <li><a href="#">Колбаса</a></li>
    <li><a href="#">Макароны</a></li>
    <li><a href="#">Тушёнка</a></li>
</ul>

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

В качестве примера можно привести ситуацию с разметкой подобной информации:

Колбаса 100 гр. 250 руб.
Макароны 100 гр. 18 руб.
Тушёнка 100 гр. 75 руб.

С одной стороны — это типичная таблица:

<table>
<tr>
    <td>Колбаса</td>
    <td>100 гр.</td>
    <td>250 руб.</td>
</tr>
<tr>
    <td>Макароны</td>
    <td>100 гр.</td>
    <td>18 руб.</td>
</tr>
<tr>
    <td>Тушёнка</td>
    <td>100 гр.</td>
    <td>75 руб.</td>
</tr>
</table>

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

И тут возникает понимание, что дизайнер, в общем-то, прав:

И дальше? А дальше уже решать вам, в каждой ситуации. Остаётся только добавить, что таблица — это развившийся список, в который внедрены дополнительные механизмы, облегчающие поиск и визуальную группировку данных по строкам и столбцам. Если эти механизмы не работают, а вам всего лишь нужно провести горизонтальные линии у каждого пункта, то задумайтесь — таблица ли это? И так далее… Интересно, правда?

Продолжение следует…

Комментарии

41

Однозначно список определений )

Колбаса - dt, цена и вес - dd, dd. Но холиварить не будем все же ;)

ура, наконец!

а я всё ссылки жду обещанные в конце доклада (на Джона Олсона и прочее что так быстро промелькнуло)

Если допустить, что последнее - таблица, возможно таки стоит сделать шапку, но c display:none
Как в таком случае с семантикой? :)

Я встречал решения, в которых, в угоду семантике, использовались скрытые блоки. И они мне всё-таки кажутся излишним фанатизмом. Для начала стоит определить цель — если вы скрываете данные (заголовок таблицы) от пользователя, то рассчитываете, что их кто-то прочитает — либо читалка сайтов, либо поисковик, либо они будут видны в представлении с отсутствующими/другими стилями.

В общем, сплошная неоднозначность, идущая из компромисса между лёгкостью и логичностью кода ;)

Видимо, фанатизмом в какой-то мере страдаю — периодически делаю в формах legend с display:none (оно в links красиво смотрится, да).
Даже помню откуда началось, с http://webstandards.org
А вообще, помню, на хабре был интересный топик, календарь таблица или список.

Фанатизм в нашем деле скорее полезен ;)
А календарь, имхо, всё-таки таблица, ибо существует полезная вертикальная выборка по дням недели.

Если в перечне несколько сущностей и их атрибуты - это dl. Но если атрибуты сами становятся сущностями, через которые можно что-то определять, тут уже таблица. То есть таблица - более сложная семантическая система, в ней как бы две смысловые плоскости (например, таблица следования поездов или таблица Пифагора).
Поэтому по логике пример с продуктами - все-таки таблица. Просто потому что выбирать здесь можно и по весу, и по цене.
С другой стороны, это все может быть не так важно :)).

Ох, чёрт, забыл, что тэги не прокатят.

Почему не:

<div class="vcard">
<h3 class="fn">Алексей Рыбаков</h3>
<address class="email">alex@example.com</address>
</div>
?

Последнее я бы сделал так:

<dl>
<dt>Колбаса</dt>
<dd>
<span class="quantity">100 гр.</span>
<span class="price">250 руб.</span>
</dd>
...
</dl>

Почему не: <div class="vcard">…

Потому, что я демонстрировал второй уровень семантики, а дальше — уже третий, с микроформатами.

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

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

К тому же, во второй части пойдёт речь о именовании элементов и их комбинации, а это уже не разметка как таковая.

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

<ul class="buy-list">
<li>Колбаса — <span class="weight">100 гр.&lt/span> за <span class="price">250 руб.</span></li>
<li>Макароны — <span class="weight">100 гр.&lt/span> за <span class="price">18 руб.&lt/span></li>
<li>Тушёнка — <span class="weight">100 гр.&lt/span> за <span class="price">75 руб.&lt/span></li>
</ul>

Я позволил себе немного его подрихтовать - иначе он выглядит не по-человечьи. Я не использую dl-dd-dt потому что в данном случае мы скорее имеем дело с неупорядоченным потоком сознания (ну и нет здесь связи вида определение - раскрытие смысла). Опять же - так этот список выглядеть будет тогда, когда есть необходимость в семантике.

Вадим, вот вопрос необходимости семантики - он ведь важный. А действительно, зачем семантика? Кроме стандартных преимуществ. Надо подумать.

Последний пример выглядит вырванным из контекста

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

Я бы всё-таки сделал так...

<table>
<tr>
<th scope="row">Колбаса</th>
<td>100 гр.</td>
<td>250 руб.</td>
</tr>
<tr>
<th scope="row">Макароны</th>
<td>100 гр.</td>
<td>18 руб.</td>
</tr>
<tr>
<th scope="row">Тушёнка</th>
<td>100 гр.</td>
<td>75 руб.</td>
</tr>
</table>

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

Интереснее был бы пример с чем-то вроде отдельно стоящих блоков с неким контентом внутри, когда нету даже четко выраженной иерархии что с чем кто от чего. Или, например, пример с не самыми простыми формами. Помнится я впал в экстаз от вот этой формы :)
http://xhtml.ru/2005/11/28/css-forms/

Помнится я впал в экстаз от вот этой формы

Ну, ничего экстатического в этих формах нет, но я согласен, что вёрстка сложных форм — это отдельная весьма интересная тема, которую в своё время поднял Алексей Рыбаков: «Создаём сложные формы без таблиц» — часть первая, часть вторая

Мне кажется, здесь лучше использовать список. Т.к. информации довольно мало и смысловая нагрузка минимальна.

Меня вот мучает вопрос. А какой практический смысл в семантической верстке? Нет, мне очень нравится вся эта правильность, но кому это в итоге будет полезно? Автора в рассчет не берем )

pepelsbey, замечательно. Тогда еще один вполне закономерный вопрос: когда?

Не вдаваясь в практику, и только с точки зрения теории, пример с таблицей как раз не так уж и неоднозначен (насколько семантика вообще может быть однозначной). То, что там написано, таки стоит делать таблицей, потому что это таблица. А неоднозначности я бы описал так:

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

- Для отображения не по ячейкам в CSS есть замечательное срдество: table, tr {display: block;} td {display: inline;}

Последнее, очевидно, убивается наличием IE, но я специально хотел прокомментировать все только с точки зрения теории :-)

Автор, сделай CSS для принтера…

Понял, исправлюсь исправился.

таки стоит делать таблицей, потому что это таблица

Честно говоря, я бы тоже сделал это таблицей, приведя всё к нужному виду простыми CSS-свойствами. Но высокая идея семантической теории очень часто зарубается на корню суровой практикой. Дай бог нам гибкий CSS3 и хороших браузеров, и мы сделаем всё красиво.

pepelsbey, а стоит ли игра свеч при нынешнем развитии HTML?

Вот такая философская задачка (на примере такого текста):

Я вышел из автобуса, зашел в магазин, купил: хлеба, молока, колбасы и пошел домой.

С точки зрения логики и русского языка: «хлеба, молока, колбасы» - это список, внутри параграфа. А с точки зрения меня, как верстальщика HTML не валидная (да и не семантическая по меркам HTML) конструкция: список, внутри параграфа...

PS пример про колбасу, макароны и тушенку из статьи, лично я б сверстал таблицей.

PS PS pepelsbey, в предыдущем сообщении тег <B> не закрыл, удалите все сообщение, а то совсем не красивое оформление...

ИМХО табличные данные - всегда надо верстать в таблице.

Много данных, мало данных, и как это смотриться - по-хорошему это вопросы представления(дизайна), а не содержания(разметки).

Корень зла, как мне кажется в том, что сделать реально семантическую верстку на HTML+CSS - нельзя. Набор семантических элементов html крайне скуден, он заставляет "натягивать" наши обьекты реального мира на семантику имеющихся элементов. Да и CSS мало что может....

PS: XML и XSLT спасут мир.

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

А насчёт скудности HTML — я не зря писал про второй и третий уровни семантики.

Большое спасибо, Вадим! Замечательная статья :)
Бегу читать продолжение…

Ну вот так всегда - захочешь сократить коммент - придется писать второй =)

Проблема HTML не в том что тегов мало,... а в том что они создавались с подглядыванием на печатное дело. Поэтому каждый тег несет свою собственную печатную семантику . Можно создать очень большое количество уровней абстракции поверх нижнего слоя, но вам все равно придется платить за это тем, что размещая на странице трактор (или визитку), его телом будет блок, его характеристики будут списком, название заголовком, надпись на боку - параграфом. ....

Можно обмануть нормальных пользователей, написав соответствующие стили изменив стили отображения элементов так, чтобы они казались чем-то еще. А как мы будем обманывать устройства для чтения с экрана? Скажем чтобы эти параграфы читало нормально - а вот эти параграфы - это совсем не параграфы - это на самом деле определения характеристик трактора!

А потом когда обманем этих....придут следующие...и тд и тп.... Стоит ли начинать?

PS: Если следовать букве семантики - пограничных случаев не бывает. Если следовать здравому смыслу - их более чем предостаточно.

Я говорил про губительность непосредственного XML, разобранного при помощи XSL и раскрашенного при помощи CSS, а связка XML+XSL->HTML на клиенте вполне ничего.

Вот такие статьи нужно демонстрировать вначале книги, а не начинать с описи всех тегов. Черт, ну почему никто не возьмется и не объяснит все, как было и как стало, с самого начала и до самого конца? Что такое DOCTYPE и как его формулировать, как верстать в каких случаях (как раз статья на эту тему) и что нужно делать для того, чтобы не пришлось переделывать через два года? Автор, вам большое спасибо, обратите внимание, сколько раз вас сохранили в социалках. На ваш блог подписываюсь.

Только у меня Outlook при экспорте vcard через Operator и Tails Export отображает имя-фамилию чем-то, но не кириллицей? При экспорте с Вашего сайта проблема с кодировкой та же. Что это и что делать?

интересная статья :)
--------------------------
прочитав множество постов о том, что последний пример - "однозначно" таблица, захотела и свою точку зрения высказать.
Однозначность мог бы внести только контекст.
Так как это может быть, например, и просто список цен на эти продукты (знаков препинания не хватает только). :)

Дай бог нам гибкий CSS3 и хороших браузеров, и мы сделаем всё красиво

Так всё же... CSS3-таблица или нет?

HTML вот уже 10 лет со своей семантической вёрсткой пытается развиваться в никуда. Поскольку путь ложен, то воз и ныне там. Вот объясните, зачем язык визуального форматирования превращать в язык логического форматирования. Если задача у него - форматирования визуальное? Идти надо в противоположном направлении. Подальше от CSS. Даёшь визуальный HTML! Что означает абсолютно визуальные шаблоны. Куда по желанию, можно уже вставлять и логические элементы.