Тег <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> в реальных проектах?

Комментарии (11)


  1. DenisSel
    23.02.2022 17:47
    +2

    С моей точки зрения верстка как явление уже давно должна была умереть. Если посмотреть на HTML как на набор строгих правил оформления контента в web, можно сделать вывод о возможности автоматизации этого процесса. Процесс верстки должен выглядеть примерно так Дизайн->Анализ изображения ИИ->Компиляция HTML->Код HTML. Вся семантика, доступность, адаптивность и т.д. нужна исключительно устройствам для корректного вывода контента, а не людям и делать ее должен ИИ


    1. vmkazakoff
      23.02.2022 21:40

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

      К сожалению чтобы описать обычным языком что-то сложное, придется объяснять нейросети детали. Она может их не понять и придется повторять другими словами или "договориться о терминах". Первое будет чем-то похоже на попытку управлять машиной с помощью голосового бота по мобильному телефону, а второе... приведет нас обратно к языку разметки)))

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

      В общем нет, спасибо. Давайте пока мы ручками)))


    1. Pavel1114
      24.02.2022 07:12

      можно ведь пойти ещё дальше. Зачем промежуточная компиляция в html? Html это для человеков. Пусть браузеры напрямую получают изображение и какое то строгое описание интерактива.
      А вообще проблема в том что компьютеру нужно строгое ТЗ, а в мире вёрстки хорошо, если под 2 варианта разрешения экрана есть макет. Но со временем, думаю, автоматизации в вёрстке станет больше.


  1. pavelsc
    23.02.2022 19:45
    +10

    <div class="footer">

    Не вижу ничего плохого в такой верстке. К сожалению при переводе на русский слова accessibility и availability переводятся как "доступность". На первый вариант, он как раз в статье, традиционно кладется болт. Бизнес беспокоит доступность контента для поисковых систем, а не то, чтоб кто-то со скрин-ридера прочел. Может быть для разработчиков муниципальных сайтов за бюджет accessibility и прописана в ТЗ, а всем остальным рекомендую не загоняться. Плохо это div внутри span и верстать таблицами :)


    1. vsh797
      24.02.2022 13:31
      +1

      Accessibility в вебе — это не сложно на самом деле. И семантические интерактивные элементы — важная его часть. Иначе получится postman. Который из-за отсутствия семантики почти не юзабелен. А вот тег footer, действительно, не принципиален.


  1. raamid
    23.02.2022 22:15
    +1

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


  1. Gigatrop
    24.02.2022 00:42

    Можно во всех ситуациях использовать div, кроме тех, где очевидно ломается что-то, или иногда ломается. Например, если у вас админка, в которой слепой человек не сможет работать, даже если всё будет доступным, то делать такую админку доступной - не имеет смысла. Или если в любом случае всё будет делаться мышкой, то перемещение табом можно вообще выкинуть. Если вы на таком проекте работаете, то доступностью вы просто потратите время и деньги, и будете зря что-то доказывать коллегам. Просто подумайте в каждом случае что вам нужно, а что нет, а не слушайте советы идеального мира.

    Если бы была возможно писать теги вообще без указания их тег-имени, было бы ещё лучше. Потому что это был бы контейнер. А прочие особенности и назначения можно задавать в атрибутах. Плюс в том, что это опционально, и дробится на сколько угодно нюансов. Так когда-то поступили со style, так же можно поступить и с именем тега. Сейчас теги имеют как минимум 3 назначения, то есть являются контейнером, семантикой и имеют разный принцип работы. А как же разделение ответственности? Свалили всё в одну кучу, поэтому приходится писать статьи, чтобы как-то договориться как с этой кучей работать.


  1. Antenshi
    24.02.2022 11:03

    Частично согласен и с автором статьи и с коментами к ней. Разнообразие тегов HTML5 просто визуально более быстро помогает понять где гланый блок, а где колонка или конкретная статья, но если блочные теги перевести в div со своим классом, а также соблюдать отступы, то менее понятной верстка не станет. Новые теги HTML5 не несут в себе особых свойств, они по большому счету остаются просто блочными элементами. По этому не вижу ничего плохого в сипользовании <div> и никакого супа из них. Несколько ранее, например когда браузера не поддерживали css свойство border-radius и приходилось вкладывать кучу div-ов друг в друга, чтобы нарисовать рамку с закругленными углами, вот это был суп (блок под границы и по блоку на каждый угол, а если границы рисовал накуренный дизайнер, то по блоку на куждую сторону). И тогда при соблюдении табуляции не сожно было разобрать где что.


  1. jesaiah4
    24.02.2022 11:05

    мне больше не зватает блочного тэга как <P> ну чтобы если рядом стоят не разделялись маргином


  1. wadowad
    24.02.2022 12:46

    Проблема в том, что новые "html5 элементы" создавались для разметки основной части документа, но на практике чаще используются для разметки страницы. И Ваш пример с header, main и footer тому подтверждение.


  1. SergeiMinaev
    24.02.2022 13:00
    +4

    Меня, наверное, закидают тапками, но всё-таки выскажусь. Не считаю полезным излишне скурпулёзный подход к семантике HTML при наличии множества других проблем. Стоит кому-то написать <div class='btn'>, как его тут же обвинят во всех смертных грехах - "Изверг! Да как ты посмел? Да ты ухудшаешь доступность и делаешь этот мир хуже! А мы, в отличие от тебя, делаем этот мир лучше - это даже на страничке нашей компании написано!". Но, при этом, считается совершенно нормальным для любой фигни использовать сверх-тяжёлые фреймворки и библиотеки, с которыми условный лендинг будет откровенно тормозить на слабых устройствах. Почему бы не считать излишнюю тяжеловесность сайтов чем-то, что ухудшает доступность? По-моему, было бы логично.

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

    Или же интерфейс с иконками без подсказок в title - пока не кликнешь, не узнаешь, что эта иконка означает.

    Или раздутие DOM десятками тысяч элементов - об этом, мне кажется, вообще мало кто запаривается.

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

    PS: Простите, накипело. Просто, в большинстве случаев, когда речь заходит о семантическом HTML, его приверженцы рассуждают так, будто не существует никаких других проблем в мире веб-разработки, и всем необходимо думать только о том, какой тег использовать вместо div.