Frontender Magazine

Искусство семантики HTML, часть 1

В 2014 году говоря о семантике в HTML, нельзя не отметить достижения в этой области.

Есть section, header, aside, footer, main и даже menu! У нас в распоряжении есть всё необходимое, верно? Тогда почему же мы продолжаем делать вот так?

<body class="article">
<div class="content">

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

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

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

Элемент hr представляет собой тематический разрыв уровня абзаца, т.е. изменение места действия в истории или переход к другой теме внутри раздела в справочнике.

Ух ты! Вот в этом месте мне мне стало действительно интересно. Я должен узнать больше! Какими ещё допущениями я руководствовался при вёрстке?

Как насчёт скромного элемента абзаца?

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

 <section>
     <p>Последнее изменение: 2001-04-23</p>
     <p>Автор: fred@example.com</p>
 </section>

Однако, это было бы лучше разметить как:

 <section>
     <footer>Последнее изменение: 2001-04-23</footer>
     <address>Автор: fred@example.com</address>
 </section>

Или:

<section>
    <footer>
        <p>Последнее изменение: 2001-04-23</p>
        <address>Автор: fred@example.com</address>
    </footer>
</section>

Ладно, это не так впечатляет, но всё же, применение более подходящих тегов footer и address — это круто. Считая, что я уже знаю всё, что только можно знать про семантику абзацев, я увидел в спецификации примечание:

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

<p>К примеру, это фантастическое предложение содержит пункты про</p>
<ul><li>колдунов,
  <li>перемещение быстрее скорости света и
  <li>телепатию,</ul>
<p>и подробнее рассматривается ниже.</p>

Другими словами, «нет никакой ложки».

Сквозная модель h1-h6

Плана документа (Document Outline), позволяющего использовать несколько тегов h1h6, основываясь на разделении документа на разделы, не существует.

Это принцип, который живёт в спецификации HTML, но по сути является фикцией в реальном мире. Это фикция потому что в браузерах он не воплощен, и нет никакого повода считать, что когда-нибудь будет. — Стив Фолкнер

Честно говоря, для меня слышать такое — это своего рода облегчение, потому как мне никогда не казалась удобной или понятной концепция множественных элементов h1 или h2 на странице. Чувство неуклюжести быстро нарастало при попытках вспомнить, какие из элементов начинают новый контекст раздела, и сколько заголовков я уже использовал. Делать проще — это здорово.

Разметка документации

Я занимаюсь исследованиями в области документации для разработчиков, и мне захотелось взглянуть на теги pre и code, чтобы убедиться, что я правильно их использую. code для ссылок внутри предложения, как например внутри этого, и pre для длинных кусков кода наподобие blockquote.

Что ж, эти допущения оказались в основном верными, но как я увидел, обычно удаётся подобрать более подходящие и более выразительные элементы. Я обнаружил ещё пару элементов, которые были специально созданы для документации кода, kbd и samp. Для меня они особенно значимы, потому что решают они две задачи:

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

Детализация кода

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

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

Вы можете поинтересоваться, какие же преимущества дают элементы data перед атрибутами data-*. Элементу data можно установить атрибут value, и когда-нибудь браузеры научатся использовать его совместно с атрибутом sortable элемента table, предоставляя авторам и пользователям механизм сортировки таблиц.

Примечание: Что касается поддержки браузерами сортировки таблиц, то тут есть большие пробуксовки, и я пока не видел ни одного рабочего примера. К тому же, раздел спецификации API DOM в HTML 5.1, посвященный этому,— это сплошная каша. Но когда это появится в браузерах, не забудьте указать роли aria-sort нужным элементам заголовка таблицы. (Спасибо Рею Камдену за ликбез.)

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

Элемент figure представляет собой поток содержимого, возможно содержащий подпись, который самодостаточен (вроде завершённого предложения) и обычно упоминается как единое целое из основного потока документа.

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

<p>В <a href="#l4">листинге</a> мы можем увидеть описание базового
интерфейса API.</p>
<figure id="l4">
  <figcaption>Листинг 4. Описание базового интерфейса API.</figcaption>

  interface PrimaryCore {
    boolean verifyDataLine();
    void sendData(in sequence<byte> data);
    void initSelfDestruct();
  }

</figure>
<p>Это API требует использования UTF-8.</p>

Ого! Это вполне толково, не правда ли? Подумайте, сколько книг вы прочитали, в которых были такие маленькие элементы figure с краю страницы, поясняющие кусок кода.

Списки определений: незаметные рабочие лошадки

Мой любимый и, по моему мнению, самый недооцененный элемент HTML в спецификации — список определений (dl). Он предназначен для разметки пар имя—значение в содержимом. Это понятие может включать в себя всё, от списка предлагаемых услуг с их описаниями до простого компонента «предыдущая статья / следующая статья», как внизу каждой страницы моего блога. Этот элемент идеально подходит для документирования истории правок страницы, причин и следствий, или, на удивление, вообще любого списка, в котором используется группировка с заголовками. До прочтения спецификации я даже не догадывался, что, оказывается, вполне допустимо иметь один dt (термин) и несколько dd (определений). Вот отличный пример из спецификации, указаны различные произношения в английском, хотя определение одно и то же.

<dl>
  <dt lang="en-US"> <dfn>color</dfn> </dt>
  <dt lang="en-GB"> <dfn>colour</dfn> </dt>
  <dd> A sensation which (in humans) derives from the ability of
  the fine structure of the eye to distinguish three differently
  filtered analyses of a view. </dd>
</dl>

Проницательные читатели и знатоки HTML могут поинтересоваться насчёт редко применяемого элемента dfn и о том, как он вписывается в семантику списков описаний. dfn спецификация описывает так: «определяющее вхождение термина». В сочетании с элементами abbr и a он может значительно облегчить читателю задачу поиска первого появления термина в тексте. Вот пример из спецификации:

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

<p><dfn><abbr title="устройство открывания гаражных ворот">УОГВ</abbr></dfn> —
это устройство, позволяющее командам исследователей открывать ирисовую диафрагму.</p>
<!-- ... далее в документе: -->
<p>Тил'к активировал своё
<abbr title="устройство открывания гаражных ворот">УОГВ</abbr>,
и Хаммонд отдал команду открыть диафрагму.</p>

С использованием элемента a ссылку можно сделать явной:

<p><dfn id=gdo><abbr title="устройство открывания гаражных ворот">УОГВ</abbr></dfn> —
это устройство, позволяющее командам исследователей открывать ирисовую диафрагму.</p>
<!-- ... далее в документе: -->
<p>Тил'к активировал своё
<a href=#gdo><abbr title="устройство открывания гаражных ворот">УОГВ</abbr></a>,
и Хаммонд отдал команду открыть диафрагму.</p>

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

Это только начало

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

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

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Kevin Suttle
Автор:
Kevin Suttle
GitHub:
kevinSuttle
Twitter:
@kevinSuttle
Сaйт:
http://kevinsuttle.com/
Антон Хлыновский
Переводчик:
Антон Хлыновский
GitHub:
subzey
Twitter:
@subzey

Комментарии (13 комментариев, если быть точным)

Автар пользователя
RamallahS

Спасибо! Очень буду ждать продолжения!!!

Автар пользователя
SilentImp

@RamallahS знаешь, я — тоже :) Хотя бы на английском, для начала.

Автар пользователя
nikitakiselev

Очень не хватало такой статьи =)

Автар пользователя
SlaF

Интересная статья =) Мне вообще интересна тема семантической разметки.

Автар пользователя
mistakster

Авторам настоятельно рекомендуется рассматривать элемент div как элемент на крайний случай, когда никакой другой элемент не подходит.

Мне кажется, что этот «совет» из спецификации опускает значимость тега div ниже плинтуса и ведёт к тому, что неопытные разработчики будут придумывать семантический смысл где его нет.

Смотрите что происходит с тегами section и article на типовом сайте — они лепятся вообще от балды и, чаще всего, служат для группировки контента. Считаю, что отсутствие хоть какого-то заголовка h1-h6 у такого блока является индикактором неправильного использования структурного элемента. Хоть в спецификации наличие заголовка и носит рекомендательный характер, но по факту становится своего рода «Best practice». Будьте уверены, если структурный элемент сопровождается заголовком, то он применён к месту. А вот если заголовка нет, то — не факт.

Ещё раз. Не нужно путать структурные элементы (например, section и article) и группирующие элементы (например, div и main) между собой.

Так же отсутствие контента при наличии структурного элемента с заголовком является грубой ошибкой. Я видал много примеров типа:

<section> <h1>Page header</h1> <h2>Sub header</h2> </section>

Очевидно же, что это никакой не раздел документа, а несколько объединённых между собой заголовков — нужен <div>!

Мой совет — не ищите чёрную кошку в тёмной комнате, особенно если её там нет.

Автар пользователя
sergius-source

А потом приходят сеошники и говорят, что в этом месте нам не надо использовать <h1> и он должен использоваться только один раз на странице. И <h1> превращается в <div class="title">. А <h2> можно использовать только в приделах статьи и он превращается во что-то типо <div class="subtitle">. А <h3> вообще надо удалить. А вот этот дополнительный <article> давай удалим, потому-что не понятно как его Яндекс распарсит... Все очень сыро, и теория(спецификация) опять идет вразрез с практикой. Впрочем, как и всегда.

Автар пользователя
SilentImp

Считаю, что отсутствие хоть какого-то заголовка h1-h6 у такого блока является индикактором неправильного использования структурного элемента.

article представляет независимый самостоятельный блок. Там не то что заголовка, там даже текста может не быть. Почему ты пришел к таким странным выводам?

div действительно стоит применять тогда, когда нет более подходящего элемента6 но это не значит «пихать куда не надо section».

<section> <h1>Page header</h1> <h2>Sub header</h2> </section>

Вообще тут нужен почивший в бозе hgroup а сейчас пожалуй header

Автар пользователя
mistakster

Так все структурные элементы про контент. Представь себе заголовок (а он тоже является структурным элементом) без контента. Странно, не правда ли? В спецификации нет запрета на отсутствие контента. Зато есть такое:

A general rule is that the article element is appropriate only if the element's contents would be listed explicitly in the document's outline.

«Основное правило таково, что элемент article можно использовать, только если контент элемента может быть явно отображен в плане документа»

У меня простая логика: нет контента — нет <article>. @SilentImp, расскажи почему ты думаешь, что отсутствие контента в таких ситуациях — это норма. Зачем нужна пустая статья?

<article style="background-image: url(image.jpg); background-size: cover" title="Картинка с изображением продукта и рекламным слоганом"></article>

А такая статья имеет право на жизнь?

Авторам настоятельно рекомендуется рассматривать элемент div как элемент на крайний случай, когда никакой другой элемент не подходит.

Изначально я процитировал фразу, которую можно легко начать трактовать как: «Используйте что угодно кроме div». Но это совсем не так. Спецификация адаптирована под алгоритм: «если — то, иначе если — то… (и так много раз) иначе <div>». В повседневной жизни человек так не мыслит. Крайний случай — это что-то экстраординарное. В веб разработке мы в 99,999% ситуациях имеем сдело с описываемый «крайним случаем». Поэтому формулировка сбивает с толку и подталкивает делать глупости.

Автар пользователя
iofjuupasli

Зачем вообще "семантическая" верстка?

Заботиться об ограниченных пользователях - дело, конечно, хорошее, только никто ведь искренне не верит в это.

Или об ограниченных устройствах. Чтобы они из-за того, что не могут отобразить контент, как задумывалось, показывали хотя бы как-то, чтобы человек мог нормально интерпретировать. Только на практике таких устройств просто нету - о попытке "распарсить интернет" можно только мечтать, а семантическая верстка никак не приближает к этому чудесному, открытому связанному интернету. Хотя вообще-то для этого существует на самом деле понятие "открытое API", которое как раз предназначено для получения "чистых данных".

Семантика и метаданные - есть различные специализированные на этом средства, вроде RDF и прочие.

Использовать меньше классов? Зачем? Если, например, писать на Jade, то размер вовсе не меняется, а итоговый HTML будет отличаться незначительно. К тому же, не понятно, как определять нормальные селекторы, если известные методики стилизации (BEM, SMACSS и в особенности OOCSS) в самом своем фундаменте загромождают классы - факт, конечно, грустный, но иначе никак не получается. Нельзя просто взять, и не думать о стилях при написании HTML. Еще, кстати, в этих методиках не рекомендуют использовать селекторы с названием элементов - и понятно, почему, сам до этого дошел быстро.

Разумным выглядит попытка семантической версткой помочь поисковым машинам лучше интерпретировать контент. Но если это действительно значительно влияет на поисковую выдачу - это нужно изучать отдельно, и пусть тогда этим занимаются SEO-специалисты, и пусть они лезут в верстку и меняют вездесущие div'ы на article.

HTML нужен браузеру, а не пользователю. Браузеру же не важно, что содержится на страничке, главное - отобразить корректно.

Автар пользователя
murashki

Надо будет почитать что там нового в этом HTML5, а то от жизни отстал ))

Автар пользователя
a-x-

@iofjuupasli, с языка снял. Я вижу в семантической вёрстке только одно практическое преимущество — облегчение поддержки. Если html семантичный, то беглым взглядом можно понять, что декларируется в коде, а как теоретический концепт она прекрасна.

Такую же пользу, в частности, несёт программирование в функциональном стиле (а ля Haskell), на мой взгляд — сразу понятно что примерно происходит.

Автар пользователя
ostinred

@SilentImp, hgroup снова начинают активно использовать, я например всегда все заголовки в

<

header> беру в

<

hgroup>:

При просмотре схемы документа просматривается логика документа.

Автар пользователя
OlegZavrazhin

Ребят, очень ждем продолжения статьи. Нужна часть 2. Готов проявить инициативу и помочь со сбором информации, если требуется, на общественных началах.