1.16. Контентная модель HTML5

Язык разметки HTML формирует структуру веб-страницы, а теги используются для идентификации типа содержимого на странице. Семантика HTML5 добавляет каждому тегу ещё больше смысла, помогая эффективно организовывать контент и использовать теги по назначению.

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

Модель содержимого HTML5

Контентная модель (content model), или модель содержимого, описывает, какой тип содержимого следует ожидать внутри элемента и какие элементы могут быть вложены в другие элементы. Большинство элементов принадлежат одной категории или нескольким категориям одновременно.

К содержимому элемента относится текст и его дочерние элементы. Если элемент не содержит текст (отличный от пробелов между элементами) и любой другой элемент, он принадлежит «никакой» модели содержимого.

1. Типы содержимого

Рис. 1. Категории контента

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

  • Мета содержимое
  • Потоковое содержимое
  • Секционное содержимое
  • Заголовочное содержимое
  • Текстовое содержимое
  • Встроенное содержимое
  • Интерактивное содержимое

Секционное, заголовочное, текстовое, встроенное и интерактивное содержимое относятся к потоковому содержимому. Мета содержимое иногда может относиться к потоковому содержимому. Мета содержимое и интерактивное содержимое иногда относятся к текстовому содержимому. Встроенное содержимое также относится к текстовому содержимому, но часть элементов также является интерактивным содержимым.

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

2. Основные категории содержимого

2.1. Мета содержимое

<base>, <link>, <meta>, <noscript>, <script>, <style>, <template>, <title>

К мета содержимому относятся элементы, которые содержат информацию о HTML-документе, устанавливают взаимосвязь HTML-документа с другими документами (например, таблицами стилей css), отвечают за внешний вид или поведение контента на странице. Элементы из другого пространства имён, чей смысл связан с метаданными, также относятся к мета содержимому.

2.2. Потоковое содержимое

<a>, <abbr>, <address>, <area> (если он является потомком элемента <map>), <article>, <aside>, <audio>, <b>, <bdi>, <bdo>, <blockquote>, <br>, <button>, <canvas>, <cite>, <code>, <data>, <datalist>, <del>, <details>, <dfn>, <dialog>, <div>, <dl>, <em>, <embed>, <fieldset>, <figure>, <footer>, <form>, <h1>, <h2>, <h3>, <h4>, <h5>, <h6>, <header>, <hr>, <i>, <iframe>, <img>, <input>, <ins>, <kbd>, <label>, <link> (если его присутствие внутри тела документа допускается), <main>, <map>, <mark>, MathML, <math>, <menu>, <meter>, <nav>, <noscript>, <object>, <ol>, <output>, <p>, <picture>, <pre>, <progress>, <q>, <ruby>, <s>, <samp>, <script>, <section>, <select>, <small>, <span>, <strong>, <sub>, <sup>, SVG, <svg>, <table>, <template>, <textarea>, <time>, <u>, <ul>, <var>, <video>, <wbr>, текст

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

2.3. Секционное содержимое

<article>, <aside>, <nav>, <section>

Секционное содержимое — содержимое, определяемое областью заголовков и колонтитулов. Каждый элемент секционного содержимого потенциально имеет заголовок и схему (outline).

2.4. Заголовочное содержимое

<h1>, <h2>, <h3>, <h4>, <h5>, <h6>

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

2.5. Текстовое содержимое

<a>, <abbr>, <area> (если он является потомком элемента <map>), <audio>, <b>, <bdi>, <bdo>, <br>, <button>, <canvas>, <cite>, <code>, <data>, <datalist>, <del>, <dfn>, <em>, <embed>, <i>, <iframe>, <img>, <input>, <ins>, <kbd>, <label>, <link> (если его присутствие внутри тела документа допускается), <map>, <mark>, MathML, <math>, <meter>, <noscript>, <object>, <output>, <picture>, <progress>, <q>, <ruby>, <s>, <samp>, <script>, <select>, <small>, <span>, <strong>, <sub>, <sup>, SVG, <svg>, <template>, <textarea>, <time>, <u>, <var>, <video>, <wbr>, текст

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

2.6. Встроенное содержимое

<audio>, <canvas>, <embed>, <iframe>, <img>, MathML, <math>, <object>, <picture>, SVG, <svg>, <video>

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

2.7. Интерактивное содержимое

<a> (если присутствует атрибут href), <audio> (если присутствует атрибут controls), <button>, <details>, <embed>, <iframe>, <img> (если присутствует атрибут usemap), <input> (если значение атрибута type не равно hidden), <label>, <select>, <textarea>, <video> (если присутствует атрибут controls)

Интерактивное содержимое предполагает взаимодействие с пользователем. Атрибут tabindex также может сделать любой элемент интерактивным содержимым.

3. Дополнительные категории содержимого

3.1. Явное содержимое

<a>, <abbr>, <address>, <article>, <aside>, <audio> (если присутствует атрибут controls), <b>, <bdi>, <bdo>, <blockquote>, <button>, <canvas>, <cite>, <code>, <data>, <details>, <dfn>, <div>, <dl> (если он содержит по крайней мере одну пару термин-описание), <em>, <embed>, <fieldset>, <figure>, <footer>, <form>, <h1>, <h2>, <h3>, <h4>, <h5>, <h6>, <header>, <i>, <iframe>, <img>, <input> (если значение атрибута type не равно hidden), <ins>, <kbd>, <label>, <main>, <map>, <mark>, MathML, <math>, <menu> (если значение атрибута type равно toolbar), <meter>, <nav>, <object>, <ol> (если он содержит по крайней мере один элемент <li>), <output>, <p>, <pre>, <progress>, <q>, <ruby>, <s>, <samp>, <section>, <select>, <small>, <span>, <strong>, <sub>, <sup>, SVG, <svg>, <table>, <textarea>, <time>, <u>, <ul> (если он содержит по крайней мере один элемент <li>), <var>, <video>, текст, не являющийся пробелом между элементами

Как правило, элементы, принадлежащие модели потокового или текстового содержимого, должны иметь минимум один узел, который имеет явное содержимое и для него не задан атрибут hidden. Явное содержимое делает элемент непустым. Это обеспечивается тем, что элемент содержит потомка с текстом или каким-либо содержимым, которое пользователь может слышать (элемент kbd><audio>), видеть (элемент <canvas>, <img> или <video>) или каким-либо образом взаимодействовать с ним (интерактивные элементы форм).

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

3.2. Элементы, поддерживающие скрипт

<script>, <template>

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

3.3. Корневое секционное содержимое

<blockquote>, <body>, <details>, <dialog>, <fieldset>, <figure>, <td>

Кроме секционного содержимого есть несколько элементов, являющихся корневыми секционными. Они выделены из секционного содержимого, но также могут иметь собственную структуру заголовков, а разделы и заголовки внутри этих элементов не взаимодействуют со структурой заголовков их родителей.

4. Прозрачная модель содержимого

<a>, <audio>, <canvas>, <del>, <ins>, <map>, <object>, <video>

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

  • Здравствуйте. Всё перечитал, но нигде не нашёл. Во что обернуть много форм? Они у меня вынесены за и облачены в , плюс каждая форма в .

    Формы разные: выбор станции метро, отправка заявки, просмотр статуса заказа и другие.

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

      • Елена, спасибо большое за ответ! У меня там не только формы, но и нумерованные списки и прочая лабудень, типа интерактивных форм (не form). Хочется указать яндексу, гуглу и другим, что это неважный контент и индексировать его необязательно.

        Обернуть в aside? или?

        • Пожалуйста! Элемент aside вместе с заголовками так же участвует в формировании оглавления страницы. Для чего это вообще было задумано: чтобы человек с плохим зрением мог свободно ориентироваться в содержимом страницы при использовании программы чтения с экрана. HTML5 outline алгоритм до сих пор не реализован во всех браузерах, поэтому, как я думаю, смысл использования новых тегов в разметке больше в удобстве, то есть не нужно задавать дополнительные классы или идентификаторы. Хотя если у вас на странице две боковые колонки, то вся прелесть минимизации разметки теряется. Поэтому секционные элементы, которые формируют оглавление страницы, можно и не использовать вовсе.
          И если вы вынесете эти блоки в боковую колонку, не пострадает ли от этого юзабельность?
          В отношении повторяющегося контента и его неиндексации можете почитать разъяснение гугл по этому вопросу https://support.google.com/webmasters/answer/66359?hl=ru. А с закрытием от индексации вовсе нужно действовать осторожно, дабы не попасть под фильтры ПС.

  • Добрый вечер, Елена!

    Что лучше для выделения главного содержимого на странице?

    Содержимое статьи

    или

    Содержимое статьи

    • Добрый день, Николай! С точки зрения семантики, если на странице всего одна статья, то ее не нужно заключать в элемент article. Атрибут main разрешен как для элемента main, так и article. Хотя для article я не видела на практике применения атрибута main, только микроразметка itemscope itemtype=»https://schema.org/BlogPosting».

      • Я подумал, получается, если в article ставить role=main, то мы переопределяем role=article, которая идёт по умолчанию…
        С одной стороны вроде логично, так как если всё главное — это только article, то зачем ещё тег main добавлять, когда можно только роль поставить… а с другой, у всех main стоит ))

        Спасибо за ответ! 🙂

        • То есть у вас будет несколько article и вы для всех собираетесь указывать role=»main»? И вы делаете проект для слабовидящих пользователей?

          • Нет, для слабовидящих не делаю… просто увлёкся, грамотно хочу сделать по стандартам.
            Там где несколько article (страница категории), там же идёт section, а в нём несколько article. У section можно сделать role=main.

            Ну а в общем, я так делать не буду, потому что все используют тег main.

          • Вообще-то, пока эта часть стандарта не реализована в браузерах, и все эти секционные элементы нужны, опять же, для создания HTML5 document outline (оглавление документа), которое поможет слабовидящим пользователям ориентироваться по структуре веб-страницы.

          • У Яндекса в справке есть рекомендация делать вёрстку по стандартам W3C и ссылка на спецификацию. В общем, правильная структура HTML-кода вряд ли лишней будет. Может ещё они особо и не учитывают семантику, но, думаю, в будущем идёт к этому.

          • Стандарты W3S — это то, что является официальным руководством, а часть нововведений HTML5 все еще в черновиках и рекомендация, у них на сайте так и написано — эта секция является ненормативной. Но согласна, что к порядку надо сразу себя приучивать ; -)

          • Без правил и порядка, не понятно, как двигаться, а так — есть цель и инструкция, как к ней идти 🙂

          • Молодец! Приятно видеть организованных и целеустремленных людей )))

          • https://uploads.disquscdn.com/images/1957f8946c2b3029b3fb82551a6672761517de56642160f3041cfd9584369694.png

            Не совсем понятно с прозрачным «а» и анонимными боксами. То есть, если «а» в блоке div, то и его логику группировки наследует?

            В приведённой картинке группировочная логика та же самая, как-будто вместо «а» были бы просто «div» или чтобы соблюсти это нужно ещё «a» в дополнительные «div» обернуть?

            Сколько блочных боксов в этом div-е?

          • Не логику группировки, а ожидаемые (разрешенные) элементы, которые могут находиться внутри ссылки. Кстати, ссылка без атрибута href не имеет смысла.
            Тип элемента от содержимого не меняется, ссылка как была, так и осталась строчным элементом, просто ее контентная модель разрешает ей оборачивать любой элемент из категории потокового содержимого.

          • https://uploads.disquscdn.com/images/45bc3fd9293d8fff4b9dcf111cb0346c37efef2e5b5683ec5e118da4b03ed90b.png

            Хм… то есть, в приведённом в данном сообщении примере задача: в шапке сайта (header) сделать 2 блока (1 группирует название и слоган; 2-ой включает просто отдельную ссылку на что-либо). Сделать эти блоки ссылками, использовать минимум элементов.

            Правильно будет на скриншоте? Header — секция, блочный. В нём «a» строчный, оборачивает 2 параграфа. Отдельная ссылка заключена в блочный элемент «p».

            Поскольку в блочном элементе не могут быть одновременно строчные и блочные элементы, то в виду того, что «p» блочный, «а» будет автоматически обёрнут в анонимный блок, который и будет группировать название и слоган?

          • Я бы сделала так:
            <header>
            <a href=»» class=»logo»>
            <span class=»site-url»>Site.ru</span>
            <span class=»site-description»>Site description</span>
            </a>
            <a href=»» class=»header-link»>Link</a>
            </header>

          • Так задача: сгруппировать название и слоган, так как они логически связаны, но отделить другую ссылку в отдельный блок. Соответственно, 2 полученных блока будут связаны header (шапкой сайта). Там просто у меня в header ещё и nav есть, он блочный. Соответственно, если так сделать, как Вы — это будет один блочный бокс из 3-х ссылок по отношению к nav.

          • https://uploads.disquscdn.com/images/112ed20d6f21bebae581d3312e4f98c716235d10cedc2a9c05bb4ea6fb2260e8.png

            Вся шапка выглядит так. Интересно, сохраняется ли там 4 блока или 5? (4, если название и слоган обёрнуты в анонимный бокс, так как «а» строчный среди блочных… или в header таким образом 5 блоков будет и чтобы было 4 нужен дополнительный группировочный div вокруг названия и слогана внутри «a»?)

          • O_o. Безумная разметка, конечно. Давайте по порядку. Анонимный блок — это когда текст находится в блоке-контейнере наряду с другими элементами, например, <header>
            какой-то текст
            <nav>
            <a href=»»>Ссылка 1</a>
            <a href=»»>Ссылка 2</a>
            </nav>
            </header>

          • Спасибо за комплимент! )))
            С текстом понятно! А вот в приведённом примере чтобы название сайта и слоган были логично сгруппированы всё-таки div нужен ещё, которым 2 этих параграфа обернуть стоит или не нужен?

          • Завтра отвечу 😉

          • Хорошо! 😉
            Насколько понимаю спецификацию, div — это группировочный элемент, а вот «a» — нет. Но, при этом пишется, что «a» в div-e наследует его свойство размещать в себе потоковые элементы, а вот группировочные свойства наследует или нет — не понятно. По идее, было бы логично, если бы наследовал (или оборачивался анонимно чем-то группировочным), чтобы не писать лишние div-ы в разметке

          • Цитата из вашей статьи:

            «Блочные элементы могут содержать как строчные, так и блочные элементы, но не оба типа элементов сразу. При необходимости, строки текста, принадлежащие блочному контейнеру, могут быть обёрнуты анонимными контейнерами, которые будут вести себя внутри блока как элементы со значением display: block;, а строчные элементы обёрнуты элементом «p». Блочные элементы могут содержаться только в пределах блочных элементов.»

            То есть, если следовать данному утверждению, в приведённом примере «a» должны оборачиваться в «p» или в другой блочный бокс

          • Я еще там написано,что «Разделение элементов на блочные и строчные используется в спецификации HTML до версии 4.01. В HTML5 эти понятия заменены более сложным набором категорий контента, согласно которым каждый HTML-элемент должен следовать правилам, определяющим, какой контент для него допустим.»

          • div не нужен. Немного подкорректировала, nav на мой взгляд, лишний, но так рекомендуется оформлять код по стандарту html5. <header>
            <a href=»/» class=»site-url»>
            <h1 class=»logo»>Название сайта</h1>
            <p class=»site-description»>Краткое описание сайта</p>
            </a>
            <nav>
            <ul>
            <li><a href=»»>Публикации</a>
            <ul>
            <li><a href=»»>Начальный уровень</a></li>
            <li><a href=»»>Продвинутый уровень</a></li>
            </ul>
            </li>
            </ul>
            </nav>
            <form action=»» method=»get»>
            <input name=»s» placeholder=»Искать здесь…» type=»search»>
            <button type=»submit»>Поиск</button>
            </form>
            <div class=»toggle-btn»>
            <span></span>
            </div>
            </header>

          • Считаете, что название сайта в h1?
            Я думал по этому поводу, изначально у меня стояло в шапке название h1, а в статье h2. Потом всё-таки h1 из шапки убрал и сделал название статьи (в article) h1, потому что смотрел выдачу Яндекса по разным запросам, практически все сайты в топе в шапке не имеют тега заголовка. Да и наверное, всё же он и нелогичен в header, потому что страница — это какая-то статья, а название в шапке — это колонтитул, а не заголовок раздела

            details всё же я решил использовать, потому что спецификация не говорит, что нельзя его для навигации использовать, какой-то семантической роли по умолчанию у него не указано (как, например, у article по умолчанию role=article). А использовать Яваскрипт и скрытие по умолчанию в дисплей «ноне» списка категорий не хочется.

            Div — не нужен, спасибо за ответ и потраченное время 🙂

          • Это разметка в соответствии с рекомендациями w3s. Js бояться не стоит, разве что вы в нем плохо разбираетесь. И я настаиваю на своем варианте. Но, конечно, это ваше дело 😉

          • Учту Вашу настойчивость 🙂
            Спасибо ещё раз за комментарии и помощь 🙂

          • ))) Пожалуйста ☺