Зачем семантика
Семантика значит выбирать тег по смыслу, а не по внешнему виду. <div> и <button> можно стилизовать одинаково, но кнопка из коробки умеет фокус, нажатие с клавиатуры (Enter и Space) и сообщает скринридеру роль «кнопка». Div не умеет ничего из этого.
Семантика нужна трём «читателям»:
- вспомогательным технологиям: скринридер строит дерево доступности из тегов и даёт навигацию по заголовкам и областям страницы;
- поисковикам: им проще понять, где основной контент, где навигация, где статья;
- разработчикам:
<nav>читается быстрее, чем<div class="nav-wrapper">.
Каркас страницы
<body>
<header>Логотип, поиск</header>
<nav aria-label="Основное меню">...</nav>
<main>
<article>
<h1>Заголовок статьи</h1>
<section>
<h2>Раздел</h2>
<p>Текст</p>
</section>
</article>
<aside>Похожие материалы</aside>
</main>
<footer>Контакты</footer>
</body>
<main>: основной уникальный контент. На странице один видимый<main>.<header>и<footer>: шапка и подвал страницы или отдельной статьи. Внутри<article>они относятся к статье.<nav>: крупные блоки навигации, не каждая группа ссылок.<article>: самостоятельный кусок, который имеет смысл вне страницы: пост, карточка товара, комментарий.<section>: тематический раздел со своим заголовком. Если заголовка нет, скорее всего нужен<div>.<aside>: побочный контент, связанный косвенно: сайдбар, врезка.
<div> и <span> никто не запрещал: это тег без смысла для группировки и стилизации. Ошибка не в div, а в div вместо кнопки, ссылки или списка.
Заголовки
Уровни h1-h6 строят оглавление документа. Правила простые: не прыгать через уровни (h2 сразу за h4 сбивает структуру), выбирать уровень по смыслу, а размер задавать CSS. Алгоритм «outline», где каждый section начинал свою иерархию с h1, в браузерах так и не реализовали и убрали из спецификации, так что на него не рассчитывай.
Кнопка или ссылка
- Ссылка
<a href>ведёт куда-то: другая страница, якорь, файл. Открывается в новой вкладке, копируется адрес. - Кнопка
<button>выполняет действие: отправить форму, открыть модалку, удалить.
Частая ошибка: <a href="#" onclick="..."> для действия или <div onclick> вместо кнопки. Ещё одна: <button> внутри <form> по умолчанию имеет type="submit", поэтому кнопка «Отмена» без type="button" отправит форму.
Формы
<form>
<label for="email">Почта</label>
<input id="email" type="email" name="email" autocomplete="email" required>
<fieldset>
<legend>Доставка</legend>
<label><input type="radio" name="d" value="courier"> Курьер</label>
<label><input type="radio" name="d" value="pickup"> Самовывоз</label>
</fieldset>
<button type="submit">Оформить</button>
</form>
<label>связывает подпись с полем: клик по подписи ставит фокус, скринридер зачитывает подпись.placeholderподписью не считается: он исчезает при вводе.- Правильный
type(email,tel,number,date) даёт нужную клавиатуру на телефоне и встроенную валидацию. <fieldset>и<legend>группируют связанные поля, например радиокнопки.
Списки, таблицы, медиа
- Набор однотипных пунктов (меню, карточки) это
<ul>/<ol>с<li>. Скринридер скажет «список, 5 пунктов». <table>для табличных данных, не для раскладки. Заголовки столбцов в<th scope="col">, подпись в<caption>.<img alt="...">: alt описывает смысл картинки. Декоративной картинке ставятalt="", тогда скринридер её пропустит. Без атрибута alt вообще скринридер может зачитать имя файла.<figure>и<figcaption>: иллюстрация с подписью.<time datetime="2026-10-15">15 октября</time>: машиночитаемая дата.
Метаданные в head
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Название страницы</title>
<meta name="description" content="Короткое описание для сниппета">
</head>
<!doctype html> включает стандартный режим рендеринга (без него браузер уходит в quirks mode). lang нужен скринридеру для произношения и переводчику. viewport без этой строки мобильный браузер рисует страницу шириной около 980px и уменьшает.
Частые ошибки
- Кликабельный
<div>вместо<button>. - Заголовок выбран по размеру шрифта, а не по уровню.
<section>без заголовка как замена div.<br>для отступов и<table>для сетки.- Поле без
<label>, только с placeholder.
Что спросят на собесе
- Что такое семантическая вёрстка и зачем она нужна.
- Чем
<article>отличается от<section>и от<div>. - Когда ссылка, а когда кнопка; какой
typeу кнопки по умолчанию. - Зачем
<!doctype html>,langи метаviewport. - Как правильно подписать поле формы и картинку.