Pull to refresh
2679.85
RUVDS.com
VDS/VPS-хостинг. Скидка 15% по коду HABR15

Раздоры вокруг <div>

Reading time 11 min
Views 21K
Original author: Scott O'Hara
Тег <div> — это самый универсальный и широко используемый HTML-элемент. Сам по себе <div> не представляет ничего, но он, в то же время, позволяет разработчикам превратить его почти во всё что угодно. Делается это посредством использования CSS (для стилизации), JavaScript (для функционала) и ARIA (для обеспечения доступности контента).

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

Грубые нарушения при использовании <div> выявить сравнительно просто (подробнее об этом поговорим ниже). Но мы дошли до того, что кто-то может назвать «образцом недоступности контента» полностью правильное использование <div>, или, как минимум, пример лёгкого отклонения от правильности. В таких ситуациях говорят о том, что «кому-то стоило бы вместо <div> воспользоваться семантическим HTML-элементом».

Тег <div> приходит на вечеринку, где его встречает команда A11y

Ладно. Притормозим немного. Прежде чем дружно задирать нос перед применением тегов <div> — давайте вспомним о том, что контекст — это важно.

Конечно, всегда, когда это возможно, нужно использовать семантические элементы. Но предлагаю проявить осторожность, создавая такую атмосферу, когда может показаться, что любой вариант использования <div> — это плохо… или — что замена некоего <div> на «более семантический» элемент способна улучшить доступность некоего документа.

Прежде чем об этом поговорить — ненадолго вернёмся в прошлое и заглянем туда, откуда взялся тег <div>.

Семантическая (деградация) эволюция <div>


Элемент <div> появился в стандарте HTML 3.0. Он представлял собой «участок» контента. Вот его первоначальное описание: «Элемент DIV… представляет разные виды содержимого. Например — глава, раздел, аннотация, дополнение».

В HTML 3.2 элементы <div> и <center> были определены, в сущности, как один и тот же элемент.

А именно, <center> рассматривался как «сокращение» для конструкции <div align=center>. Он стал частью стандарта из-за того, что Netscape создала этот элемент до реализации стандартизированного элемента <div>. В IT эту ситуацию сравнивают с тем, как коровы или овцы протаптывают дорожки по пастбищам. Одно из животных идёт по пути первым, а все остальные бездумно следуют за ним, не пытаясь найти более короткий или безопасный маршрут. В нашем случае <center> — это путь в никуда.

Интересно тут то, что исходное определение тега <div> можно рассматривать как очень раннюю идею, которая однажды, в более поздних версиях HTML, превратилась в идею разбиения контента на разделы. Не говорю, что в то время создатели стандарта стремились именно к этому, но очевидно, что тогда в HTML не хватало специфических элементов для распространённых контейнеров, нужных для разбиения контента на разделы или его группировки. Элемент <div> или <center>, как минимум, давал альтернативу тем, кто ранее размещал материалы в элементах <table>.

Элемент <div> в HTML 4.01


В стандарте HTML 4.01 определение <div> стало не таким детальным в плане того, что может представлять этот элемент. Там говорится об использовании <div> в качестве универсального инструмента для структурирования контента. В HTML 4.01, кроме того, можно наблюдать исчезновение <center> (Облом!) и появление элемента <span>. Там элемент <div> предлагается использовать для структурирования на уровне блоков контента, а <span> — как универсальный контейнер для встроенного содержимого.

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

Современное определение <div>


Знаете… нечто вроде «определения», но… речь идёт о <div>… Извиняюсь. Просто не могу это удалить.

В HTML5 и в материалах «живого стандарта» HTML, который актуален в настоящий момент, описание элемента <div> стало таким:
Элемент div совершенно не несёт в себе какого-то особого смысла. Он представляет свои дочерние элементы. Он может использоваться с атрибутами class, lang, title для обозначения семантики, общей для некоей последовательности элементов. Ещё его можно использовать в элементе dl, в качестве контейнера для групп элементов dt и dd.

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

В MDN можно найти дальнейшие инструкции для разработчиков по использованию <div>.

В HTML AAM <div> назначена роль ARIA generic. Определение этой роли в ARIA похоже на определение <div> в HTML:
Безымянный элемент-контейнер, который, сам по себе, не имеет никакого семантического значения.

Представление пустого места


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

В результате получается, что правильное применение <div> может оказаться непростым для тех, кто ожидает наличия чётких указаний на то, что такое «хорошо» и «плохо» в разметке доступного контента. Взгляните, например, на следующий код:

<div>Hi there, I'm a paragraph of content!</div>

К каким проблемам может привести оформление абзаца подобным образом? Об этом мы поговорим позже, а пока давайте посмотрим на несколько сценариев использования <div>, которые легче классифицировать как «плохие» и «хорошие».

▍Очевидный пример неправильного использования <div>


Самый распространённый пример того, как не надо применять <div> — это когда с помощью этого элемента создают интерактивный контент вроде «ссылок» или «кнопок»:

<div class=button onclick=foo()>
  Click me!
</div>

Не вникая в особые подробности (можете почитать статью про role=button на MDN), могу сказать, что <div> — это, по своей природе, не интерактивный элемент. Одна лишь стилизация не способна превратить <div>, например, в кнопку. Даже добавление обработчика события click не позволяет соблюсти все условия, необходимые для воссоздания доступной кнопки.

Но кто-то может пуститься во все тяжкие, создавая собственный элемент div-button и оснащая его полноценными механизмами поддержки клавиатуры. Такой элемент может представлять себя в виде кнопки и в различных состояниях, характерных для кнопок (кнопка может быть, например, отключённой, нажатой, развёрнутой). Его создатель может, кроме того, поработать над тем, чтобы он хорошо функционировал бы в режиме высокой контрастности Windows. Если кто-то и правда решит всем этим заняться — пожелаем ему удачи. Но всё это потребует куда больше усилий, чем использование стандартного элемента <button>. Правда, если сделать div-button хорошо, то в этом не будет ничего совершенно несовместимого с жизнью. Правда?

▍Элемент <div> и неправильное описание структуры документа


Теперь, если говорить о структурных контейнерах содержимого, можно быстро определить, используется ли <div> вместо более семантического элемента, взглянув на визуальное представление такого элемента. Ещё один способ заключается в анализе HTML-кода, названий классов или ID, используемых для элементов (если только для всего этого применяются более или менее понятные имена):

<body>
  <div class=header>
    ...
  </div>
  <div id=main>
    ...
  </div>
  <div class=footer>

  </div>
</body>

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

Выше были описаны примеры неправильного использования <div>, которые легко найти и исправить. Это может быть сделано путём замены элементов <div> на другие, более подходящие элементы (вроде <main>). Можно, при необходимости, задействовать ARIA для назначения элементам атрибутов role, state, aria-* (например — <div role=main>).

▍Элементы <div>, с которыми всё хорошо


Разберём пару примеров совершенно допустимого применения <div>.

Для начала — пусть имеется набор абзацев или других элементов, содержащих текст на языке, который отличается от основного языка документа (веб-страницы). Тут <div> можно использовать с атрибутом lang, содержащим подходящий языковой тег. В этот <div> можно включить весь контент на другом языке, это позволит указать на то, что этот язык использован в документе совершенно сознательно.

<div lang=fr>
  <h3><font color="#3AC1EF">▍...</font></h3>
  <p>...</p>
  <ul>
    <li>...
    <li>...
    <li>...
    ...
  </ul>
  ...
</div>

Здесь применение контейнера <div> с атрибутом lang гораздо легче применения этого атрибута к каждому элементу, включённому в этот контейнер. Кроме того, если исходить из предположения о том, что этот контент представляет собой нечто особенное, используемое только на конкретной странице, окажется, что применение <div> тут допустимо без всяких вопросов. Немного ниже мы ещё к этому вернёмся…

Следующий пример, где в применении <div> нет никаких проблем, заключается в структурировании контента для целей стилизации:

<main>
  <div style="display: flex; ...">
    <div style="flex: ...">
      <h1>...</h1>
      <!-- sub-heading / meta data could go here -->
    </div>
    <div style="flex: ...">
      <!-- social follow links -->
    </div>
  </div>

  <!-- other semantic elements / content go here -->
</main>

Тут элементы <div> применяются в роли контейнеров для элементов <h1> и другого контента, имеющегося в начальной части статьи и предваряющего её основную часть. Здесь, для размещения контента, используется flex-макет (для упрощения примера здесь применены атрибуты style).

Тут вы можете подумать о том, что это — не такой уж и удачный пример, так как применение <div> для структурирования контента — это, вроде бы, не очень правильно. Может, тут стоило бы использовать больше доступных элементов?

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

Универсальное применение любых других HTML-тегов


Помимо <div> есть и немало других, более семантических HTML-элементов, представляемых как универсальные (role=«generic»). Среди них, например, такие, как <address>, <kbd>, <abbr>, <body>. Соответствующая роль назначается им неявным образом.

Если пойти немного дальше, то окажется, что есть и другие элементы, вроде <header>, <footer> и <section>, которые, что часто встречается в разметке страниц, выглядят как generic-элементы. Причина этого кроется в том, что роли ARIA, управляющие доступностью элементов, имеют весьма специфические цели. У HTML-элементов, кроме того, имеется чётко определённая семантика, указывающая на предполагаемый способ использования их разработчиком. Но не у всех HTML-элементов семантика в точности совпадает с ролями ARIA, которые заданы им неявным образом.

Например — элемент <header>, когда он находится внутри элемента <body>, становится баннером — role=banner. Это значит, что до тех пор, пока между <body> и <header> не будет элемента <main>, элемента, предназначенного для разбиения контента на разделы, или корневого элемента раздела, элемент <header> будет виден как banner (абстрактная роль landmark)

Но в HTML <header> — это не всегда баннер. Этот тег полностью подходит, в том числе — и с семантической точки зрения, на роль потомка элемента <article> или <section>. Но в таком контексте теги <header> не представляют собой контейнеров, содержащих, в основном, контент уровня всего сайта, а не конкретной страницы.

Получается, что если <header> не вложен в <body>, он становится универсальным элементом, таким же, как <div>. Это относится, кроме того, и к элементу <footer>.

<body>
  <header> I'm a banner! </header>
  <main>
    <header> I am NOT a banner! </header>
    ...
  </main>
</body>

Если говорить об элементе <section>, то он, по умолчанию, тоже является универсальным. Он может быть представлен как элемент с ролью region — если ему назначено доступное имя. Например:

<!-- a generic section -->
<section>
  <h2><font color="#3AC1EF">...</font></h2>
  ...
</section>

<!-- a 'region' landmark -->
<section aria-labelledby=h>
  <h2 id=h>...</font></h2>
  ...
</section>

Причина, по которой элемент <section> ведёт себя именно так, заключается в крайнем распространении его неправильного использования, когда в этот раздел включают всё, что нужно и не нужно.

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

Доступность страницы, на которой полно region-элементов, ухудшится. Ведь если знаком «Важно!» помечено всё вокруг, то окажется, что ничего важного, на самом деле, нет.

Возникает такое ощущение, что всё это очень похоже на <div>. Правда?

Суровость семантики


Если говорить о паре «правильных» примеров использования <div>, с уверенностью можно сказать, что в них можно было бы воспользоваться, соответственно, элементами <section> и <header>. В этом есть смысл с семантической точки зрения. Но роль этих элементов ничем не будет отличаться от роли уже используемых в примерах элементов <div>.

То же самое касается и одного из первых моих примеров, который я обещал обсудить позже, где элемент <div> играл роль контейнера абзаца:

<div>Hi there, I'm a paragraph of content!</div>

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

Единственный HTML-элемент, который предназначен для оформления абзацев — это <p>. Абзацы создаются неявным образом для каждого нового «блока» текста на странице. Поэтому, прежде чем разыграть карту «Используй семантический HTML и получишь в награду доступность», важно подумать о реальном воздействии на пользователя, о том, стоит ли сейчас разыгрывать эту карту. Лучше ли будет явным образом использовать <p>? Да, лучше. Способствует ли это тому, что пользовательские стили смогут единообразно настраивать внешний вид абзацев? Да. Об этом ли обычно говорят, обсуждая использование <div> вместо <p>? Обычно — нет.

Нам нужно беспокоиться о великом множестве проблем, которые могут возникнуть в сфере доступности контента. Надо ли разработчикам менять элементы <div> на другие, такие же универсальные, элементы, или на элементы, которые могут дать пользователям лишь небольшие улучшения, учитывая то, что имеется множество других, гораздо более срочных проблем, которые надо решить… Я не знаю. Полагаю, тут имеется множество сложностей, которые просто обходят молчанием.

Не поймите меня неправильно: я не защищаю варианты использования <div> в случаях, в которых лучше использовать семантические элементы.

Пишите семантический HTML-код. Используйте его как стандарт. А ещё, может быть, не стоит беспокоиться слишком сильно, когда другие не используют семантический HTML, если то, что они создают, не приводит к проблемам с доступностью? Или, если призываете кого-то пользоваться семантическим HTML, предельно чётко описывайте проблему, которую это может решить. Семантические элементы HTML — это не только доступность контента. Они помогают другим инструментам, которые работают с HTML, их гораздо легче, чем бескрайнее море <div>, понять разработчикам, модифицирующим чужую разметку.

Помните о том, что смысл элементов <div> заключается в том, чтобы ничего не представлять. Они могут быть практически всем чем угодно… Главное — не делать из них «суп». Полагаю, что все мы можем сойтись хотя бы на том, что элементы <div> для этого не предназначены.

О «супе» из <div>


Я, когда работал над черновиком этой статьи, пользовался презентацией Эрика Бэйли о пересечении производительности и доступности.

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

Всё закончилось хорошо. Думаю, всё закончилось хорошо.

Да, всё нормально.

Сталкивались ли вы с примерами неправильного использования <div> в реальных проектах?

Tags:
Hubs:
+28
Comments 12
Comments Comments 12

Articles

Information

Website
ruvds.com
Registered
Founded
Employees
11–30 employees
Location
Россия
Representative
ruvds