<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)
pavelsc
23.02.2022 19:45+10<div class="footer">
Не вижу ничего плохого в такой верстке. К сожалению при переводе на русский слова accessibility и availability переводятся как "доступность". На первый вариант, он как раз в статье, традиционно кладется болт. Бизнес беспокоит доступность контента для поисковых систем, а не то, чтоб кто-то со скрин-ридера прочел. Может быть для разработчиков муниципальных сайтов за бюджет accessibility и прописана в ТЗ, а всем остальным рекомендую не загоняться. Плохо это div внутри span и верстать таблицами :)
vsh797
24.02.2022 13:31+1Accessibility в вебе — это не сложно на самом деле. И семантические интерактивные элементы — важная его часть. Иначе получится postman. Который из-за отсутствия семантики почти не юзабелен. А вот тег footer, действительно, не принципиален.
raamid
23.02.2022 22:15+1Может немного не в тему, но поделюсь своим опытом. Однажды на заре своей карьеры довелось мне вставить тег <div> внутрь тега <p>. Я уже тогда понимал, что это не правильно и должно быть наоборот, просто разметка была разбросана по шаблонам и я не заметил этого до тех пор пока не стали происходить очень странные глюки. Пришлось потратить несколько часов на поиск причины. С тех пор стараюсь везде использовать <div>.
Gigatrop
24.02.2022 00:42Можно во всех ситуациях использовать div, кроме тех, где очевидно ломается что-то, или иногда ломается. Например, если у вас админка, в которой слепой человек не сможет работать, даже если всё будет доступным, то делать такую админку доступной - не имеет смысла. Или если в любом случае всё будет делаться мышкой, то перемещение табом можно вообще выкинуть. Если вы на таком проекте работаете, то доступностью вы просто потратите время и деньги, и будете зря что-то доказывать коллегам. Просто подумайте в каждом случае что вам нужно, а что нет, а не слушайте советы идеального мира.
Если бы была возможно писать теги вообще без указания их тег-имени, было бы ещё лучше. Потому что это был бы контейнер. А прочие особенности и назначения можно задавать в атрибутах. Плюс в том, что это опционально, и дробится на сколько угодно нюансов. Так когда-то поступили со style, так же можно поступить и с именем тега. Сейчас теги имеют как минимум 3 назначения, то есть являются контейнером, семантикой и имеют разный принцип работы. А как же разделение ответственности? Свалили всё в одну кучу, поэтому приходится писать статьи, чтобы как-то договориться как с этой кучей работать.
Antenshi
24.02.2022 11:03Частично согласен и с автором статьи и с коментами к ней. Разнообразие тегов HTML5 просто визуально более быстро помогает понять где гланый блок, а где колонка или конкретная статья, но если блочные теги перевести в div со своим классом, а также соблюдать отступы, то менее понятной верстка не станет. Новые теги HTML5 не несут в себе особых свойств, они по большому счету остаются просто блочными элементами. По этому не вижу ничего плохого в сипользовании <div> и никакого супа из них. Несколько ранее, например когда браузера не поддерживали css свойство border-radius и приходилось вкладывать кучу div-ов друг в друга, чтобы нарисовать рамку с закругленными углами, вот это был суп (блок под границы и по блоку на каждый угол, а если границы рисовал накуренный дизайнер, то по блоку на куждую сторону). И тогда при соблюдении табуляции не сожно было разобрать где что.
jesaiah4
24.02.2022 11:05мне больше не зватает блочного тэга как <P> ну чтобы если рядом стоят не разделялись маргином
wadowad
24.02.2022 12:46Проблема в том, что новые "html5 элементы" создавались для разметки основной части документа, но на практике чаще используются для разметки страницы. И Ваш пример с header, main и footer тому подтверждение.
SergeiMinaev
24.02.2022 13:00+4Меня, наверное, закидают тапками, но всё-таки выскажусь. Не считаю полезным излишне скурпулёзный подход к семантике HTML при наличии множества других проблем. Стоит кому-то написать <div class='btn'>, как его тут же обвинят во всех смертных грехах - "Изверг! Да как ты посмел? Да ты ухудшаешь доступность и делаешь этот мир хуже! А мы, в отличие от тебя, делаем этот мир лучше - это даже на страничке нашей компании написано!". Но, при этом, считается совершенно нормальным для любой фигни использовать сверх-тяжёлые фреймворки и библиотеки, с которыми условный лендинг будет откровенно тормозить на слабых устройствах. Почему бы не считать излишнюю тяжеловесность сайтов чем-то, что ухудшает доступность? По-моему, было бы логично.
Также частенько дизайнеры забивают на десктопные версии и большие мониторы, фокусируясь только на мобильных устройствах. В результате, при просмотре страницы на большом мониторе, каждый элемент отрисовывается с отступами по 5-10см и пара абзацев текста растягивается на несколько экранов скролла. Но об этом тоже никто особо не говорит.
Или же интерфейс с иконками без подсказок в title - пока не кликнешь, не узнаешь, что эта иконка означает.
Или раздутие DOM десятками тысяч элементов - об этом, мне кажется, вообще мало кто запаривается.
Но, конечно же, это всё не так важно. Куда важнее полностью сфокусироваться на смертных казнях для всех использующих <div> вместо <span>, закрывая глаза на все остальные менее модные проблемы.
PS: Простите, накипело. Просто, в большинстве случаев, когда речь заходит о семантическом HTML, его приверженцы рассуждают так, будто не существует никаких других проблем в мире веб-разработки, и всем необходимо думать только о том, какой тег использовать вместо div.
DenisSel
С моей точки зрения верстка как явление уже давно должна была умереть. Если посмотреть на HTML как на набор строгих правил оформления контента в web, можно сделать вывод о возможности автоматизации этого процесса. Процесс верстки должен выглядеть примерно так Дизайн->Анализ изображения ИИ->Компиляция HTML->Код HTML. Вся семантика, доступность, адаптивность и т.д. нужна исключительно устройствам для корректного вывода контента, а не людям и делать ее должен ИИ
vmkazakoff
Есть огромное число сервисов которые "генерируют код", как с рисунка, так и даже с текстового описания, написанного обычным языком.
К сожалению чтобы описать обычным языком что-то сложное, придется объяснять нейросети детали. Она может их не понять и придется повторять другими словами или "договориться о терминах". Первое будет чем-то похоже на попытку управлять машиной с помощью голосового бота по мобильному телефону, а второе... приведет нас обратно к языку разметки)))
Ну а визуальные генераторы кода, типа редимага, фигмы (из нее можно сразу сайт экспортировать) или там сторилайна - у них масса ограничений, которые обходить дольше и дороже чем написать руками, я молчу про оптимизации, внимание к мелочам и прочие детали. Что-то совсем простое - да, отлично подходит.
В общем нет, спасибо. Давайте пока мы ручками)))
Pavel1114
можно ведь пойти ещё дальше. Зачем промежуточная компиляция в html? Html это для человеков. Пусть браузеры напрямую получают изображение и какое то строгое описание интерактива.
А вообще проблема в том что компьютеру нужно строгое ТЗ, а в мире вёрстки хорошо, если под 2 варианта разрешения экрана есть макет. Но со временем, думаю, автоматизации в вёрстке станет больше.