Семантическая разметка

Семантическая разметка -- использование HTML-элементов в соответствии с их смысловым значением, а не внешним видом.

Зачем нужно

Семантика HTML решает три задачи:

  1. Доступность (a11y): screen readers используют семантику для навигации. Слепой пользователь может перейти к <nav>, <main>, <footer> горячими клавишами
  2. SEO: поисковые системы понимают структуру контента. <article> с <h1> значит больше, чем <div class="article"><div class="title">
  3. Поддерживаемость: разработчик видит <nav> и сразу понимает -- это навигация. <div class="nav-wrapper"> требует чтения CSS

Где используется

  • Любой сайт, ориентированный на SEO
  • Доступные веб-приложения (WCAG 2.1)
  • Сайты госструктур (требования по доступности)
  • Профессиональная разработка

Предпосылки

Div soup vs. семантика

Плохо: div soup

<!-- Div soup -- всё на div-ах -->
<div class="header">
  <div class="nav">
    <div class="nav-item"><a href="/">Главная</a></div>
    <div class="nav-item"><a href="/about">О нас</a></div>
  </div>
</div>
<div class="content">
  <div class="article">
    <div class="title">Заголовок</div>
    <div class="text">Текст статьи...</div>
  </div>
  <div class="sidebar">
    <div class="widget">Боковая панель</div>
  </div>
</div>
<div class="footer">
  <div class="copyright">2026</div>
</div>

Хорошо: семантическая разметка

<!-- Семантическая разметка -->
<header>
  <nav aria-label="Основная навигация">
    <ul>
      <li><a href="/">Главная</a></li>
      <li><a href="/about">О нас</a></li>
    </ul>
  </nav>
</header>
<main>
  <article>
    <h1>Заголовок</h1>
    <p>Текст статьи...</p>
  </article>
  <aside>
    <section>Боковая панель</section>
  </aside>
</main>
<footer>
  <p><small>&copy; 2026</small></p>
</footer>

Семантические элементы

<header> -- шапка

Вводная группа контента. Может содержать навигацию, логотип, поиск.

<!-- Шапка страницы -->
<header>
  <a href="/" aria-label="На главную">
    <img src="logo.svg" alt="Логотип компании" width="120" height="40">
  </a>
  <nav>...</nav>
</header>

<!-- Шапка секции или статьи -->
<article>
  <header>
    <h2>Название статьи</h2>
    <p><time datetime="2026-04-06">6 апреля 2026</time></p>
  </header>
  <p>Текст статьи...</p>
</article>

<header> можно использовать несколько раз -- для страницы и для отдельных секций/статей.

Завершающий контент: копирайт, ссылки, контакты.

<!-- Подвал страницы -->
<footer>
  <nav aria-label="Навигация подвала">
    <ul>
      <li><a href="/privacy">Политика конфиденциальности</a></li>
      <li><a href="/terms">Условия использования</a></li>
    </ul>
  </nav>
  <p><small>&copy; 2026 Компания. Все права защищены.</small></p>
</footer>

<!-- Подвал статьи -->
<article>
  <h2>Статья</h2>
  <p>Контент...</p>
  <footer>
    <p>Автор: <a href="/authors/ivan">Иван Петров</a></p>
    <p>Теги: <a href="/tags/html">HTML</a>, <a href="/tags/css">CSS</a></p>
  </footer>
</article>

<main> -- основной контент

Уникальный контент страницы. Только один <main> на странице (без hidden).

<body>
  <header>...</header>

  <main id="main-content">
    <!-- Всё уникальное для этой страницы -->
    <h1>Каталог товаров</h1>
    <section>...</section>
  </main>

  <footer>...</footer>
</body>

<main> не включает повторяющийся контент (навигацию, шапку, подвал).

Секция с навигационными ссылками.

<!-- Основная навигация -->
<nav aria-label="Основная навигация">
  <ul>
    <li><a href="/">Главная</a></li>
    <li><a href="/catalog">Каталог</a></li>
    <li><a href="/contacts">Контакты</a></li>
  </ul>
</nav>

<!-- Хлебные крошки -->
<nav aria-label="Хлебные крошки">
  <ol>
    <li><a href="/">Главная</a></li>
    <li><a href="/catalog">Каталог</a></li>
    <li aria-current="page">Товар</li>
  </ol>
</nav>

Не каждая группа ссылок -- <nav>. Используй для основных блоков навигации. Для ссылок в подвале или мелких списков -- обычный <ul>.

<section> -- тематическая секция

Группирует контент по теме. Обычно имеет свой заголовок.

<main>
  <section aria-labelledby="new-heading">
    <h2 id="new-heading">Новинки</h2>
    <ul>
      <li>Товар 1</li>
      <li>Товар 2</li>
    </ul>
  </section>

  <section aria-labelledby="popular-heading">
    <h2 id="popular-heading">Популярное</h2>
    <ul>
      <li>Товар A</li>
      <li>Товар B</li>
    </ul>
  </section>
</main>

<article> -- самостоятельный контент

Контент, который имеет смысл отдельно от страницы: статья, пост, комментарий, товарная карточка.

<!-- Статья блога -->
<article>
  <header>
    <h2><a href="/posts/42">Заголовок статьи</a></h2>
    <p>Опубликовано <time datetime="2026-04-06">6 апреля 2026</time></p>
  </header>
  <p>Текст статьи...</p>
  <footer>
    <p>Автор: Иван Петров</p>
  </footer>
</article>

<!-- Комментарий (вложенный article) -->
<article>
  <h2>Статья</h2>
  <p>Текст...</p>

  <section>
    <h3>Комментарии</h3>
    <article>
      <header>
        <strong>Пользователь</strong>
        <time datetime="2026-04-06T14:30">14:30</time>
      </header>
      <p>Отличная статья!</p>
    </article>
  </section>
</article>

Тест: если контент может быть опубликован в RSS-ленте отдельно -- это <article>.

<aside> -- дополнительный контент

Контент, связанный с основным косвенно: боковые панели, выноски, реклама.

<main>
  <article>
    <h1>Руководство по HTML</h1>
    <p>Текст руководства...</p>

    <!-- Выноска внутри статьи -->
    <aside>
      <h2>Интересный факт</h2>
      <p>Тим Бернерс-Ли создал HTML в 1991 году.</p>
    </aside>
  </article>

  <!-- Боковая панель -->
  <aside>
    <h2>Похожие статьи</h2>
    <ul>
      <li><a href="/css">Руководство по CSS</a></li>
      <li><a href="/js">Руководство по JS</a></li>
    </ul>
  </aside>
</main>

<search> -- область поиска (новый элемент)

Элемент, появившийся в HTML в 2023 году. Обозначает область с функциональностью поиска:

<!-- Поиск по сайту -->
<search>
  <form action="/search" method="get">
    <label for="query">Поиск по сайту:</label>
    <input type="search" id="query" name="q">
    <button type="submit">Найти</button>
  </form>
</search>

<!-- Фильтрация контента -->
<search>
  <label>
    Фильтр по категории:
    <select name="category">
      <option value="all">Все</option>
      <option value="html">HTML</option>
      <option value="css">CSS</option>
    </select>
  </label>
</search>

До <search> использовали <div role="search"> или <form role="search">.

Другие семантические элементы

<!-- <time> -- дата/время -->
<time datetime="2026-04-06">6 апреля 2026</time>
<time datetime="14:30">14:30</time>
<time datetime="PT2H30M">2 часа 30 минут</time>

<!-- <address> -- контактная информация -->
<address>
  <a href="mailto:info@example.com">info@example.com</a><br>
  <a href="tel:+79001234567">+7 (900) 123-45-67</a>
</address>

<!-- <mark> -- выделение релевантного текста -->
<p>Результаты поиска по запросу "HTML":
  Изучите <mark>HTML</mark> для создания веб-страниц.
</p>

<!-- <figure> и <figcaption> -->
<figure>
  <img src="diagram.png" alt="Схема HTML-документа">
  <figcaption>Рис. 1: Структура HTML-документа</figcaption>
</figure>

<!-- <blockquote> и <cite> -->
<blockquote cite="https://www.w3.org/People/Berners-Lee/">
  <p>Веб -- это просто воображаемое информационное пространство.</p>
  <footer>-- <cite>Тим Бернерс-Ли</cite></footer>
</blockquote>

Полная семантическая структура страницы

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Блог о веб-разработке</title>
</head>
<body>
  <a href="#main" class="skip-link">Перейти к содержимому</a>

  <header>
    <a href="/">Логотип</a>
    <nav aria-label="Основная навигация">
      <ul>
        <li><a href="/">Главная</a></li>
        <li><a href="/articles">Статьи</a></li>
        <li><a href="/about">О блоге</a></li>
      </ul>
    </nav>
    <search>
      <form action="/search">
        <input type="search" name="q" aria-label="Поиск по сайту">
        <button type="submit">Найти</button>
      </form>
    </search>
  </header>

  <main id="main">
    <h1>Последние статьи</h1>

    <article>
      <header>
        <h2><a href="/posts/1">Введение в HTML5</a></h2>
        <p>
          <time datetime="2026-04-06">6 апреля 2026</time> |
          Автор: Иван
        </p>
      </header>
      <p>Краткое введение в современный HTML...</p>
      <footer>
        <a href="/posts/1">Читать полностью</a>
      </footer>
    </article>

    <article>
      <header>
        <h2><a href="/posts/2">CSS Grid на практике</a></h2>
        <p><time datetime="2026-04-05">5 апреля 2026</time></p>
      </header>
      <p>Практические примеры Grid layout...</p>
    </article>
  </main>

  <aside>
    <section>
      <h2>Категории</h2>
      <ul>
        <li><a href="/cat/html">HTML</a></li>
        <li><a href="/cat/css">CSS</a></li>
        <li><a href="/cat/js">JavaScript</a></li>
      </ul>
    </section>
  </aside>

  <footer>
    <nav aria-label="Навигация подвала">
      <ul>
        <li><a href="/privacy">Приватность</a></li>
        <li><a href="/terms">Условия</a></li>
      </ul>
    </nav>
    <address>
      Связаться: <a href="mailto:blog@example.com">blog@example.com</a>
    </address>
    <p><small>&copy; 2026 Блог. Все права защищены.</small></p>
  </footer>
</body>
</html>

section vs. article vs. div

Элемент Когда использовать
<article> Самостоятельный контент (статья, пост, карточка товара)
<section> Тематическая группа с заголовком
<div> Нет семантического значения, нужен контейнер для стилей

Правило: если можешь заменить <div> на семантический элемент -- замени.

Частые ошибки

Ошибка Почему плохо Как правильно
Всё на <div> Нет семантики для a11y и SEO Используй семантические элементы
<section> без заголовка Нарушает спецификацию <section> должен иметь heading
Несколько <main> (без hidden) Только один основной контент Один <main> на страницу
<nav> для каждого списка ссылок Навигация "размывается" <nav> только для основных навигаций
<article> для несамостоятельного контента Искажённая семантика Если нельзя вынести отдельно -- это не article
<header> только для шапки сайта Упущена возможность <header> можно в <article> и <section>

Практика

  1. Возьми любой сайт, открой DevTools и посмотри, какие семантические элементы используются
  2. Перепиши div-soup пример выше на семантический HTML
  3. Установи расширение WAVE для Chrome и проверь свою страницу на accessibility
  4. Попробуй screen reader (NVDA для Windows) -- послушай, как он читает семантическую разметку vs. div-soup
  5. Создай страницу блога с <header>, <nav>, <main>, <article> (2-3 статьи), <aside>, <footer>

Связанные темы

Ресурсы