Вступление

Привет хабр! Меня зовут Николай и я Frontend-разработчик в логистическом стартапе Relog. Хочу рассказать о самых распространённых ошибках в вёрстке современных проектов.

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

Также я расскажу о работе со спецификацией HTML — какие разделы важны для нас, как для верстальщиков и как искать там информацию.

Содержание

  1. Используйте правильные теги

  2. Как правильно вкладывать теги друг в друга

  3. Работа с медиаконтентом

  4. Пишем таблицы на HTML правильно

  5. a или button? Работа с интерактивными элементами и как выбрать правильный тег

  6. Различный теги для медиа-контента

  7. Прекратите писать велосипеды! Как мы можем стилизовать дефолтные HTML-элементы

  8. Пишем доступные формы

  9. Избыточная вёрстка. Как облегчить разметку

  10. Современные фишки HTML и CSS способные облегчить нам жизнь

  11. Экспериментальные технологии, входящие в стандарт

Как правильно вкладывать теги друг в друга

Что значит правильно? Что является источником истины при работе с HTML? Конечно же это специфиакция! В данный момент существует так называемый «живой стандарт» пятой версии HTML. Это значит, что у него нет мажорных версий и он обновляется регулярно. Посмотреть последнее обновление спецификации можно здесь.

Спецификация HTML — это увесистый документ с кучей разделов. Она существует как для разработчиков браузеров, так и для нас — верстальщиков. Конкретно нас интересуют третий и четвёрный раздел (Semantics, structure, and APIs of HTML documents и The elements of HTML). Эти разделы описывают, как теги можно вкладывать друг в друга и что обозначает каждый тег.

Описание элемента

Каждый элемент имеет метаинформацию и описание.

Сверху размещены метаданные, куда включна следующая информация:

  • куда можно вкладывать тег;

  • какие теги можно вкладывать внутрь этого тега;

  • перечень аттрибутов тега (глобальные, дополнительные и ARIA);

  • информация о доступности;

  • вспомогательные данные.

Далее размещено описание тега — что он обозначает и как его можно использовать.

Спецификация элемента на примере тега <p>
Спецификация элемента на примере тега <p>

Метаданные тега

Метаданные тега <p>
Метаданные тега <p>

Метаинформация о теге включает в себя несколько пунктов:

  • Категории — обозначает, к каким типам тегов относится элемент, могут быть следующие типы:

    • Metadata content (например <meta> и <title>) — метаданные страницы, обозначающие представление или поведение содержимого, или отношение к другим документам;

    • Flow content (например <article>, <span>, <p>) — это все теги, используемые в <body>, то есть почти все в целом, за исключением некоторых мета-тегов;

    • Sectioning content (например <section>) — какие-либо большие секции, как правило имеющие конкретную структуру и заголовок;

    • Heading content (все заголовки <h1><h6>, а также тег, про который я забыл рассказать в прошлой статье — <hgroup>) — определяет заголовок секции, обозначенной явно, либо <body>.

    • Phrasing content (например <a>, <span>, <strong>) — различный, в основном текстовый контент, но включающий также некоторые элементы, которые позволяют размечать текст на уровне параграфов;

    • Embedded content (например <iframe>, <canvas>, <video>) — контент, встраиваемый извне (другие сайты, файлы, скрипты);

    • Interactive content (например <a>, <button>, <input>) — теги, с которыми пользователь может взаимодействовать;

  • Контекст использования элемента — где мы можем размещать элемент.

  • Контентная модель — важная для этой статьи часть! Это как раз то, что мы можем размещать внутри тега.

  • Tag omission — возможные сценарии, когда закрывающую часть тега можно опустить. Рекомендую не обращать внимания на этот раздел вообще, так как в современном вебе нормальной практикой является закрытие всех парных тегов.

  • Доступные аттрибуты тега.

  • Раздел, касающийся доступности. Надеюсь когда-нибудь дойдут руки написать о работе с доступностью в рамках спецификации.

  • DOM Interface — раздел, необходимый для JavaScript-разработчиков, подробно на нём останавливаться не будем.

И всё же, как правильно вкладывать теги друг в друга?

Категории элементов по HTML-спецификации
Категории элементов по HTML-спецификации

Две основные категории тегов — это Metadata (метаданные) и Flow (поточные теги). Метаданные — это то что в основном входит в <head>, а Flow — то что можно положить в <body>. Однако, некоторые мета-теги мы можем разместить в <body>, поэтому они заходят на Flow-контент (например это <noscript>, <script> и <style>).

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

Heading — это просто залоговки всех уровней, а также тег <hgroup>.

Sectioning — это большие смысловые части документа, секции.

Phrasing — небольшие слова или словосочетания, фразы. В основном это строчные элементы (по крайней мере они такими являлись в спецификации HTML4). Все остальные теги, не имеющие категории Phrasing, как правило являются блочными.

Embedded — как уже писал выше, контент, имеющий внешний источник данных, то есть не имеющий прямое отношение к HTML-документу.

Interactive — категория, пересекающаяся с Flow, Phrasing и Embedded, обозначающая все элементы, с которыми пользователь может взаимодействовать.

Проверять возможность вкладывания тегов друг в друга можено по следующему алгоритму:

  1. Смотрим на контентную модель тега, в который вкладываем.

  2. Смотрим на категории тега, который вкладываем.

  3. Если видим, что категория нам подходит и нет ограничений, то вкладываем, если нет, то вложение запрещено.

Давайте разберёмся на примере. Есть тег <section> и мы хотим вложить в него тег <b>: у секции контентая модель Flow, у <b> категории Flow, Phrasing и Palpable. Соответственно вложение допустимо.

Другой пример:

<label>
  <p>Имя:</p>
  <input type="text" name="name">
</label>

Частая задача, когда нам нужно внутри лейбла держать и инпут и его описание. Проверям:

  • Для лейбла контентной моделью является Phrasing Content, но без вложения других лейблов.

  • <p> не имеет категории Phrasing, поэтому вкладывать <p> в <label> нельзя!

  • <input> имеет категорию Phrasing, поэтому мы можем вложить его в <label>.

Если сильно упрощать, то во Flow мы можем вкладывать и Flow, и Phrasing, а во Phrasing только Phrasing.

Заключение части 2

Но всю эту простыню можно было не читать, а просто воспользоваться сервисом https://caninclude.glitch.me, написанным Александром Вишняковым и скрин которого я разместил в шапке поста. Там по аналогии с Can I Use, можно проверить, вкладывается ли один тег в другой или нет.

Ну и не забывайте валидировать код с помощью W3C Validator, который тоже сможет подсказать, правильно ли вы вкладывали теги, или нет.

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


  1. LostAlly
    06.05.2022 00:34

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

    Или я просто не понял ценности данной информации.

    С нетерпением жду продолжения.


    1. Clickrouc Автор
      06.05.2022 05:20
      -1

      Спасибо за обратную связь! Учту при написании следующей.


  1. alexnozer
    06.05.2022 05:19
    +2

    Про hgroup стоит лишь сказать, что его нет смысла использовать: он не работает так, как описано в спецификации из-за того, что ни в один из браузеров не внедрен структурный алгоритм (structure outline), поскольку с ним есть проблемы.


  1. E_STRICT
    06.05.2022 09:41
    +1

    Судя по картинки phrasing content нельзя вкладывать в heading content. Но ведь это не так?
    И вообще на основании чего создана эта картинка? В спецификации правила вложенности определяются на уровне тегов, а не на уровне модели контента.


    1. Clickrouc Автор
      06.05.2022 11:11

      Картинка из спеки: https://html.spec.whatwg.org/#kinds-of-content

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


      1. E_STRICT
        06.05.2022 11:52
        +1

        А ну тут дело в контексте. Картинка абсолютно правильная, только она не имеет отношение к вложенности тегов. В контексте данной статьи это не очевидно.
        Эта картинка иллюстрирует пересечение категорий в модели контента. Например, все теги из категории "embeded" так же принадлежат категориям "flow" и "phrasing". При этом некоторые из них (например, iframe и embed) имеют ещё и в категорию "interactive".