Тег <section> обозначает тематический раздел страницы - часть, которую можно назвать одним словом: услуги, отзывы, контакты, частые вопросы. Тег парный, закрывающий </section> обязателен. Собственных атрибутов у него нет, только глобальные вроде class и id, но к нему чаще, чем к другим тегам, добавляют aria-label - почему, разобрано ниже.
В этой статье
Для чего нужен тег section в HTML
Страница почти всегда делится на смысловые куски. У страницы компании это блоки "О нас", "Услуги", "Отзывы", "Контакты"; у статьи - крупные части текста; у каталога - фильтры и сам список товаров. Тег <section> как раз и размечает такой кусок.
Оформления он не добавляет: раздел выглядит точно так же, как в <div>. Меняется только то, что видит разбирающая страницу программа - у куска появляется статус части документа, а не случайной обёртки.
<main>
<h1>Наша компания</h1>
<section>
<h2>Услуги</h2>
<p>Что мы делаем...</p>
</section>
<section>
<h2>Отзывы</h2>
<p>Что о нас говорят...</p>
</section>
</main>
Пример: страница, разбитая на разделы
Услуги
Отзывы
Контакты
Подписи с названием тега добавлены для наглядности. На настоящей странице ничего такого не появится: границы разделов видны только в разметке.
Чем section отличается от div
Результат в браузере одинаковый - оба тега блочные и оба ничего не меняют внешне. Выбор между ними решается одним вопросом: можно ли дать этому блоку название?
Если блок называется "Отзывы клиентов" или "Как мы работаем" - это раздел, и ему подходит <section>. Если единственное название, которое приходит в голову, звучит как "обёртка для двух колонок" или "контейнер, чтобы задать отступ" - это работа вёрстки, и нужен <div>.
<div class="container">
<div class="row">...</div>
</div>
<section>
<h2>Отзывы клиентов</h2>
...
</section>
Из этого следует и обратное предостережение: массовая замена всех <div> на <section> разметку не улучшает. Когда разделом объявлено всё подряд, слово "раздел" перестаёт что-либо значить - ровно как с тегом nav, если обернуть в него каждую группу ссылок.
Заголовок внутри section и его уровень
Раз <section> - это названный раздел, название должно быть в разметке. Обычно это заголовок <h1>-<h6> первым элементом внутри. Формально валидатор за его отсутствие не ругается, но раздел без названия теряет смысл: программе непонятно, чем он отличается от соседнего.
А вот с уровнем заголовка связано самое живучее заблуждение вокруг этого тега. Считается, что браузер сам понижает уровень по глубине вложенности - прописал <h1> в каждую секцию, а дальше разберутся. Когда-то такой механизм действительно закладывали в спецификацию, но ни один браузер его не реализовал, и из спецификации его убрали. Визуально заголовок во вложенной секции браузер уменьшает, и потому кажется, что всё работает - но в дереве документа он остаётся ровно тем уровнем, который вы написали.
Задайте уровни сами и посмотрите, что получится у скринридера.
Выберите уровень для каждого заголовка:
- h1Наша компания
- h2Услуги
- h3Доставка
Структура читается правильно: каждый следующий заголовок ровно на уровень глубже предыдущего.
Уровень пропущен. Скринридер объявит переход через ступень, и слушателю покажется, что часть страницы он не услышал.
Уровни повторяются или идут вверх. Вложенность в разметке есть, а в структуре документа разделы оказались равными или перевёрнутыми - именно это и не исправляет браузер сам.
Страница осталась без первого уровня. Заголовок h1 задаёт тему всей страницы, и начинать структуру со второго уровня незачем.
Отдельный случай - раздел, название которого не нужно показывать на экране. Заголовок в таком случае не выбрасывают, а прячут специальным классом, оставляя его в разметке для скринридера. Прятать через display: none нельзя: так заголовок исчезает и для вспомогательных технологий тоже.
Как подбирать уровень заголовка для карточек в списке записей, разобрано на странице тега article.
section внутри section
Вкладывать разделы друг в друга можно, и запрос про это встречается регулярно. Условие ровно одно: у вложенного раздела своя тема и свой заголовок. "Услуги" с подразделами "Доставка" и "Монтаж" - нормальная структура.
<section>
<h2>Услуги</h2>
<section>
<h3>Доставка</h3>
<p>Сроки и условия...</p>
</section>
<section>
<h3>Монтаж</h3>
<p>Как проходит установка...</p>
</section>
</section>
Чего делать не стоит - вкладывать разделы ради вёрстки. Если внутренний <section> появился только затем, чтобы задать фон или отступ, и заголовка у него нет, это <div>. Глубина вложенности сама по себе ничего не улучшает, а разбирать такую структуру тяжелее.
Когда section становится ориентиром для скринридера
Здесь находится факт, который объясняет странное расхождение между справочниками. Одни пишут, что заголовок внутри <section> обязателен, другие - что он лишь рекомендуется и его можно заменить атрибутом. Правы и те, и другие, потому что речь про разные вещи.
Сам по себе <section> не является ориентиром: без доступного имени у него роль generic, и для скринридера он неотличим от <div>. Ориентиром region он становится только тогда, когда название у него появляется - через aria-labelledby, связанный с заголовком, или через aria-label с текстом.
<section aria-labelledby="otzyvy">
<h2 id="otzyvy">Отзывы клиентов</h2>
...
</section>
<section aria-label="Отзывы клиентов">
...
</section>
Из двух способов предпочтительнее первый: название берётся из настоящего заголовка, и текст не придётся править в двух местах. Второй подходит разделу, у которого видимого заголовка нет.
Навешивать название на каждый раздел подряд не нужно. Ориентиры полезны, пока их немного: если ими объявлена вся страница, список перестаёт помогать - ровно тот же эффект, что показан на странице тега nav. Название стоит давать разделу, к которому посетитель действительно захочет перейти напрямую.
Когда вместо section нужен article
Эти два тега выбирают вместе чаще всего, и путают их тоже чаще всего. Критерий короткий: <article> самодостаточен, <section> - часть целого.
Пост в блоге остаётся понятным в RSS-ленте и в подборке "похожие статьи" - это <article>. Раздел "Услуги" вне страницы компании не рассказывает, чьи это услуги - это <section>. Комбинировать их можно в любом порядке: разделы внутри длинной статьи, статьи внутри раздела-ленты.
Подробный разбор с проверкой на реальных примерах - на странице тега article.
Частые ошибки
Этот тег чаще других страдает от избыточного применения: его применяют там, где нужен обычный контейнер, и потом удивляются, что семантика не помогла.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
Все <div> заменены на <section> |
Разделом объявлено всё подряд, и слово перестаёт нести смысл | Оставить <section> там, где блоку можно дать название |
У раздела нет ни заголовка, ни aria-label |
Роль остаётся generic, и для скринридера раздел неотличим от обёртки | Добавить заголовок или дать название атрибутом |
Во всех вложенных разделах стоит <h1> |
Браузер уменьшает такие заголовки визуально, но в структуре остаются первые уровни | Проставить уровни вручную по реальной вложенности |
Заголовок раздела скрыт через display: none |
Название пропадает и у скринридера тоже - раздел снова безымянный | Прятать классом для визуального скрытия, оставляя текст доступным |