Теги и атрибуты
Учимся работать со списками, заголовками и атрибутами — они сделают вашу разметку осмысленной.
Атрибуты
Атрибуты — это дополнительные настройки тега. Пишутся в открывающем теге в виде имя="значение":
<img src="photo.jpg" alt="Моя фотография">
<a href="https://example.com" target="_blank">Сайт</a>
| Атрибут | Где бывает | Зачем |
|---|---|---|
href | <a> | Адрес ссылки |
src | <img>, <script> | Путь к файлу |
alt | <img> | Альтернативный текст (важно для доступности) |
target="_blank" | <a> | Открыть ссылку в новой вкладке |
class | любой | Метка для стилей CSS |
id | любой | Уникальный идентификатор элемента |
class — повторяемая метка, их может быть много с одинаковым значением. А вот id на странице должен быть уникальным — встречаться один раз.Заголовки: древовидная структура
Заголовки создают иерархию смысла. Не пропускайте уровни: сначала <h1>, потом <h2> и так далее. Так странице проще понимать поисковые системы и скринридеры.
Мой сайт
Обо мне
Проекты
Сайт для кофейни
Списки
Три вида списков: маркированный, нумерованный и список определений.
<ul>
<li>Кофе</li>
<li>Чай</li>
</ul>
<ol>
<li>Открыть редактор</li>
<li>Написать код</li>
<li>Сохранить файл</li>
</ol>
- Кофе
- Чай
- Какао
- Открыть редактор
- Написать код
- Запустить страницу
<li> может находиться ещё один список, так получаются многоуровневые меню.Форматирование текста
| Тег | Эффект |
|---|---|
<strong> | Жирный текст (смысловой акцент) |
<em> | Курсив (акцент интонацией) |
<mark> | Выделение маркером |
<br> | Перенос строки |
<blockquote> | Цитата-блок |
Семантика: <div> и <span> vs осмысленные теги
<div> и <span> — «пустые» обёртки без значения. Но у HTML есть набор семантических тегов, которые несут смысл для людей и машин:
<header>— шапка страницы или блока;<nav>— навигация;<main>— главный контент;<section>,<article>— смысловые разделы;<footer>— подвал;<aside>— боковая панель.
<header>
<nav><a href="#">Главная</a></nav>
</header>
<main>
<section>
<h2>Статья</h2>
<p>Текст статьи...</p>
</section>
</main>
<footer>© 2026</footer>
Атрибуты data-*
Любые атрибуты с префиксом data- — ваши личные «кармашки» для информации. Их не видно на странице, зато легко читать из JavaScript (урок 9) или CSS:
<button data-action="delete" data-id="42">Удалить</button>
<div data-theme="dark">...</div>
data- атрибуты нельзя. Всё, что содержит значение только для скриптов или стилей, — прячьте в data-*.Глобальные атрибуты
Существуют атрибуты, которые работают у любого тега. Самые полезные:
| Атрибут | Что делает |
|---|---|
title="..." | всплывающая подсказка при наведении |
hidden | скрывает элемент со страницы |
tabindex="0" | делает элемент доступным для перехода с клавиатуры |
lang="en" | отдельно переопределяет язык у куска текста |
draggable="true" | разрешает перетаскивание |
translate="no" | запрещает встроенный перевод для фрагмента |
<abbr title="HyperText Markup Language">HTML</abbr>
<p hidden>Этого никто не увидит.</p>
Код в тексте: <pre> и <code>
<code> показывает фрагмент кода в тексте, а <pre> сохраняет форматирование (пробелы и переносы строк). Вместе они идеально показывают примеры:
<pre><code>
const x = 5;
console.log(x);
</code></pre>
<, пишите сущность <.Правильная вложенность
HTML-теги должны вкладываться по принципу «матрёшки»: открывающий и закрывающий тег не должны пересекаться.
<ul>
<li>
<strong>Важно!</strong>
</li>
</ul>
Неправильно:
<strong><em>пересечение тегов</strong></em> <!-- так нельзя -->
HTML-сущности
Спецсимволы, которые трудно или нельзя набрать напрямую, записываются как сущности — амперсанд, имя и точка с запятой:
<p>4 < 5 — верно. Пиши — это знак тире.</p>
| Запись | Результат |
|---|---|
< | < |
> | > |
& | & |
© | © |
| неразрывный пробел |
: «№ 7», «10 кг» — число не оторвётся от единицы измерения.<b>/<i> или <strong>/<em>?
Разница между ними — в смысле, а не в виде. <strong> и <em> несут смысловой акцент, а <b>/<i> — только визуальное выделение:
<p><strong>Важно!</strong> Сохранение прошло.</p>
<p>Цена — <b>999 ₽</b></p> <!-- просто жирный текст -->
strong/em. Просто «покрасить» — b/i, или вообще span с классом.Контактный блок: <address>
Тег <address> семантически выделяет контакты автора контента — его удобно находить скриптам и скринридерам:
<address>
Автор: Иван Иванов,
<a href="mailto:ivan@mail.ru">ivan@mail.ru</a>
<a href="tel:+79990000000">+7 999 000-00-00</a>
</address>
Время: <time> и скрыто-раскрывающееся <details>
<time> хранит читаемую машиной дату, а <details>/<summary> создают раскрывающийся аккордеон без JavaScript:
<time datetime="2026-02-14">14 февраля 2026</time>
<details>
<summary>Показать ответ</summary>
<p>Текст, скрытый по умолчанию.</p>
</details>
<details open> — развернуть блок сразу. Это готовый FAQ-аккордеон: доступен с клавиатуры и не требует ни строчки JS.Изображение с подписью: <figure>
Связка «картинка + подпись» оформляется тегами <figure> и <figcaption>:
<figure>
<img src="team.jpg" alt="Команда проекта">
<figcaption>Команда WebDev Уроки, 2026</figcaption>
</figure>
Ширина и высота: где указывать
Размеры изображений раньше писали прямо в HTML. Сегодня это делают в CSS, а атрибуты Оставляют для резервирования места — чтобы страница не «прыгала» при загрузке:
<img src="photo.jpg" alt="Пейзаж" width="640" height="480">
width/height нужны, чтобы браузер знал пропорции кадра заранее. В CSS ширину ставьте в процентах — и пропорции сохранятся автоматически.Список описаний: dl, dt, dd
Тип списка для терминов и их определений — пара «ключ → значение»:
<dl>
<dt>HTML</dt>
<dd>Язык разметки гипертекста</dd>
<dt>CSS</dt>
<dd>Каскадные таблицы стилей</dd>
</dl>
dl, а не пустые div.Цитаты: blockquote и cite
Длинная цитата — <blockquote>, встроенная в текст — <q>. Источник отмечают <cite>:
<blockquote>
Хорошо структурированный код читают, как прозу.
<cite>— Анонимный разработчик</cite>
</blockquote>
<p>Он сказал: <q>Код — это текст</q>.</p>
Линии и разделы: hr
Горизонтальная линия <hr> отделяет смысловые части документа, чтобы между ними не путались читатели:
<h2>Часть первая</h2>
<p>...</p>
<hr>
<h2>Часть вторая</h2>
id в деталях
id — уникальный паспорт элемента: для якорей, JavaScript и CSS-селекторов:
<section id="pricing">Тарифы</section>
<a href="#pricing">К тарифам</a>
<!-- в JS: -->
<script>document.getElementById("pricing")</script>
id может встретиться на странице только один раз. Если блок повторяется — это класс.Классы: группа меток
Класс можно вешать на много элементов и сочетать несколько классов на одном:
<div class="card featured">...</div>
<div class="card">...</div>
<div class="card sale">...</div>
btn-primary, card--big. Дефисы и двойные дефисы стандартны (методология BEM).article против section
<article> — самостоятельная единица (пост, новость, комментарий), <section> — тематический раздел:
<section>
<h2>Новости</h2>
<article>Новость 1</article>
<article>Новость 2</article>
</section>
article. Раздел просто тематически группирует контент — это section.Выделение: mark, small, sub, sup
Мелочи форматирования, которые придают тексту характера:
<mark>Выделено маркером</mark>
<small>мелкий примечательный текст</small>
H<sub>2</sub>O — индексы
x<sup>2</sup> — степени
Пробелы в HTML: слипание
Браузер съедает лишние пробелы и переводы строк — не пишите «перенос» как несколько Spaces подряд:
<p>Один пробел</p> <!-- станет «Один пробел» -->
. Для переноса строк вне текста используйте CSS, а не десяток <br>.Переключение языка: lang на фрагменте
Можно сменить язык для отдельных слов — полезна цитатам на иностранном:
<p lang="en">Keep calm and code on.</p>
Datalist: подсказки для поля
<datalist> даёт встроенный список подсказок без JavaScript:
<input list="browsers">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Edge">
</datalist>
Готовый каркас страницы
Прогрессивный «шаблон на каждый день» — открывайте в срок и не изобретайте заново:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Название</title>
</head>
<body>
<header>Шапка</header>
<main>Контент</main>
<footer>Подвал</footer>
</body>
</html>
Как смотреть HTML глазами
«Сырую» разметку любой живой страницы видно без всяких инструментов:
- Ctrl+U — исходник текущей страницы;
- DevTools → Elements — живой HTML с уже применёнными правками браузера;
- Скопировать элемент и вставить в свой файл — быстрый черновик.
Короткая цитата: q
Цитата прямо в строке — браузер сам добавит кавычки:
Он сказал <q>код — это стихи</q> и замолчал.
blockquote, для коротких внутри абзаца — q. Кавычки приходят из языка страницы.Аббревиатуры: abbr и dfn
Расшифровка термина по наведению и определение понятия:
<abbr title="HyperText Markup Language">HTML</abbr>
<dfn>Хэш-функция</dfn> — преобразование данных фиксированной длины.
Правки: ins и del
Показывают, что добавлено и что удалено — с датой:
Цена: <del datetime="2026-01-01">990 ₽</del>
<ins datetime="2026-02-01">790 ₽</ins>
Зачёркнутое: s
Неактуальная, но оставленная информация:
<s>Старое название</s> — теперь так не называется
Подчёркивание: u
Аккуратно: подчёркивание обычно означает ссылку. Используйте редко:
<u>Неправильное написание</u>
Код и переменные: kbd, samp, var
Разные роли машинного текста:
Нажмите <kbd>Ctrl + S</kbd>.
Программа выведет <samp>OK</samp>.
Формула: <var>a</var> + <var>b</var>.
Изоляция направления: bdi
Отделляет текст с неизвестным направлением — например, ник пользователя:
Пользователь <bdi>مرحبا</bdi> оставил отзыв.
Восточная типографика: ruby
Подсказка-произношение над иероглифом:
<ruby>漢<rt>kan</rt></ruby>
Мягкий перенос: wbr
Разрешает перенос длинного слова в нужном месте, но не вставляет дефис:
https://<wbr>very-long-<wbr>path-<wbr>to-page
Группа заголовка: hgroup
Объединяет h1 с подзаголовком, чтобы поисковик видел один заголовок:
<hgroup>
<h1>Курс по CSS</h1>
<p>От основ до анимаций</p>
</hgroup>
Шаблон в разметке: template
Фрагмент, который браузер не покажет, но отдаст JavaScript:
<template id="card-tpl">
<article class="card"><h3>Заголовок</h3></article>
</template>
template невидимо и не грузится (картинки, скрипты). Идеально для повторяющихся карточек.Когда JS выключен: noscript
Сообщение пользователю без поддержки скриптов:
<noscript>
<p>Включите JavaScript, чтобы работали фильтры.</p>
</noscript>
Секция внутри секции
Вложенные смысловые куски — это нормально, если они правда самостоятельны:
<section>
<h2>Услуги</h2>
<section>
<h3>Фронтенд</h3>
</section>
<section>
<h3>Бэкенд</h3>
</section>
</section>
Внутри статьи свои части
Article может содержать собственные header и footer — например, мета-подпись:
<article>
<header><h2>Что нового в CSS</h2></header>
<p>Текст статьи...</p>
<footer><time>2026-09-20</time></footer>
</article>
Спецсимволы типографики
©, ™, длинное тире, неразрывный дефис — пишите сущностями:
© 2026 Студия
Бренд™
Справа — слева
по‑русски
Пробелы разной ширины
HTML даёт несколько видов пробелов для отступов и «прилипания»:
A B <!-- неразрывный -->
A B <!-- полукруглая (en) -->
A B <!-- круглый (em, шире) -->
A B <!-- тонкий -->
Мягкий перенос: shy
Перенос покажет дефис только при необходимости:
экстра­ординарный <!-- «экстра-ординарный» при переносе -->
Русская типографика: ёлочки
Кавычки в текстах на русском — «ёлочки», вложенные — „лапки“:
«Внешние „вложенные“ кавычки»
Дефис против тире
Разные знаки и разные роли:
крепкий мир — <!-- это тире (—) -->
сине-зелёный <!-- это дефис (-) -->
Пётр I — царь
Параграф не внутри параграфа
Вложенный <p> браузер сам разорвёт — валидатор поругается:
<!-- НЕПРАВИЛЬНО -->
<p>Текст <p>вложенный</p></p>
<!-- ПРАВИЛЬНО -->
<p>Текст</p><p>новый абзац</p>
Максимум один h1
Один главный заголовок на страницу — и он должен отражать суть:
<h1>Пиццерия «Дрова»</h1> <!-- один раз -->
<h2>Меню</h2>
<h2>О нас</h2>
Заголовки без пропусков
Если после h2 идёт h4 — структура «прыгнула». Не пропускайте уровни:
<!-- плохо: -->
<h2>Раздел</h2><h4>Подраздел</h4>
<!-- хорошо: -->
<h2>Раздел</h2><h3>Подраздел</h3>
Описательный текст ссылок
«Читать далее» ничего не говорит. Называйте, куда ведёт ссылка:
<!-- плохо -->
Подробности <a href="/tariffs">здесь</a>.
<!-- хорошо -->
<a href="/tariffs">Сравнить тарифы</a>.
Источник цитаты: cite
Название произведения или источник со словом «—»:
<blockquote>
<p>Простота — залог надёжности.</p></blockquote>
<cite>Алан Журнал, «Заметки о коде»</cite>
Строки стихотворения
Каждая строка с br, строфы — отдельными блоками:
<p>
Буря мглою небо кроет,<br>
Вихри снежные крутя...
</p>
<br> — разделитель строк, а не «отступ». Большие отступы делайте CSS.Списки внутри текста
Список может жить внутри пункта другого списка:
<ul>
<li>Фрукты
<ul>
<li>Яблоки</li>
</ul>
</li>
</ul>
Единственный main
Основное содержимое страницы маркируется один раз:
<body>
<header>...</header>
<main>Уникальный контент</main>
<footer>...</footer>
</body>
Боковая заметка: aside
Материал «в стороне» — цитата, реклама, сноска:
<aside>
<h3>Кстати</h3>
<p>Этот приём называют «прогрессивным улучшением».</p>
</aside>
Навигация: nav
Группа ссылок для перехода по сайту или странице:
<nav aria-label="Основное меню">
<ul>
<li><a href="/">Главная</a></li>
</ul>
</nav>
Несколько изображений в figure
Figure может содержать галерею с одной общей подписью:
<figure>
<img src="1.jpg" alt="Слева">
<img src="2.jpg" alt="Справа">
<figcaption>Две стороны одной луны</figcaption>
</figure>
data: машинное значение рядом
Тег <data> связывает видимый текст с машинным значением:
<data value="398">от 398 ₽</data>
Микроразметка: itemscope
Поисковики понимают смысл через schema.org-атрибуты:
<div itemscope itemtype="https://schema.org/Book">
<span itemprop="name">Как устроен код</span>
</div>
JSON-LD: структура для ботов
Разметка машинным описанием внутри script — её не видно пользователю:
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "Article", "headline": "Новость" }
</script>
ARIA: имя элемента
Если видимой подписи нет — дайте её скринридеру:
<button aria-label="Закрыть окно">✕</button>
ARIA: роль области
Атрибут role явно объявляет назначение блока:
<div role="alert">Ошибка сохранения!</div>
Скрыть от скринридера: aria-hidden
Декоративную иконку можно исключить из озвучки:
<span aria-hidden="true">🚀</span> Запуск
Паттерн visually-hidden
Текст невидим глазом, но доступен скринридеру:
<span class="sr-only">Открыть главное меню</span>
<!-- .sr-only прячет через CSS clip, а не display:none -->
Проверка орфографии: spellcheck
Браузерное подчёркивание опечаток — можно выключить:
<textarea spellcheck="false">код, а не проза</textarea>
Атрибут translate
Запрет автоперевода имён и кодов:
<p>Функция <span translate="no">parseInt</span> округляет.</p>
Перетаскивание: draggable
Простое объявление перетаскиваемого элемента:
<div draggable="true">Перетащи меня</div>
Скрыть элемент: hidden
Глобальный атрибут убирает элемент из отображения и из поиска по странице:
<p hidden>Черновик, ещё не показывать</p>
Инлайн-стиль: style
Быстро проверить оформление — но для проекта плохо:
<p style="color: red; font-size: 20px;">Красный текст</p>
Событие прямо в теге
Старый способ обработчиков — работает, но не приветствуется:
<button onclick="alert('Привет!')">Нажми</button>
addEventListener в отдельном JS-файле: HTML остаётся разметкой, а поведение — кодом. Об этом в уроках по JavaScript.Тренировка
Соберите блок «О себе» на странице:
- Заголовок
<h1>с вашим именем. - Нумерованный список «Мои навыки» из 3 пунктов.
- Вложенный маркированный список внутри одного из навыков.
- Добавьте в
<head>тег<meta name="description" content="...">.
Подсказка: картинки и ссылки — наш следующий урок.
Тег как контейнер смысла
Тег — это ярлык, который объясняет компьютеру смысл куска контента: <p> — абзац, <h1> — главный заголовок, <nav> — навигация.
Атрибут как настройка поведения
Атрибут уточняет, как ведёт себя элемент: куда вести, какого типа поле, какую показать подсказку. Без атрибутов тег — «чистая заготовка».
<a href="https://developer.mozilla.org">MDN</a> <!-- куда вести -->
<p> ничего не даст.Как «читать» тег целиком
Тренируйте чтение разметки слева направо: открывающий тег, атрибуты, содержимое, закрывающий тег. Через неделю такие куски будут читаться как обычные предложения.
<p class="lead">Вводный абзац.</p>
└─ открытие ┘└─ атрибут ┘ └─ содержимое ┘ └─ закрытие ┘
Заголовок h2: граница раздела
<h2> открывает новый раздел: всё, что относится к его теме, идёт до следующего <h2>.
<h2>Настройка</h2>
<p>Раздел про настройку начинается здесь.</p>
<h2>Запуск</h2>
<p>Следующая тема — запуск.</p>
Абзацы: что с чем соседствует
Рядом с абзацем живут другие блочные элементы: заголовки, списки, цитаты, картинки. Строчные теги работают внутри текста, а не между блоками.
<p>Первый абзац.</p>
<ul><li>Пункт после абзаца</li></ul>
<p>Второй абзац.</p>
Маркированный список: порядок неважен
Когда пункты равнозначны и их можно переставить местами — это <ul>. Примеры: увлечения, характеристики, ингредиенты.
<ul>
<li>Фотоаппарат</li>
<li>Ноутбук</li>
</ul>
<ol>. Тип списка считывают и скринридеры.Нумерованный список: порядок важен
<ol> — там, где шаги идут по порядку: рецепты, инструкции, списки приоритетов. Нумерацию браузер посчитает сам.
<ol>
<li>Откройте файл.</li>
<li>Внесите правку.</li>
<li>Сохраните.</li>
</ol>
Термин и определение: dl на практике
Словарь «термин → определение» — это <dl> с <dt> и <dd>. Удобно для характеристик товара, метаданных, FAQ.
<dl>
<dt>Процессор</dt>
<dd>Intel Core i5, 6 ядер</dd>
</dl>
Вложенные списки: оглавление и меню
Любой пункт списка может содержать внутри ещё один список — так строятся меню, оглавления, деревья.
<ul>
<li>Документы
<ul>
<li>Паспорт</li>
<li>Права</li>
</ul>
</li>
</ul>
<li>, а не «между» пунктами.Иностранные слова: lang и курсив
Слово из другого языка помечают атрибутом lang на фрагменте — скринридер озвучит его с правильным произношением.
<p>Слово <i lang="en">cookie</i> уже знакомо.</p>
dir.Строчные элементы вокруг строки
Строчные теги (a, em, code, span) живут внутри строки и не переносят её на новую строку.
<p>Текст с <strong>важным словом</strong> посреди абзаца.</p>
Почему strong, а не b
<strong> — смысловая «важность», <b> — просто визуальная жирность. Для текстов в интернете важен первый: он доносит акцент и до «чтения вслух».
<p>Аккуратно: <strong>лестница скользкая</strong>.</p>
font-weight, а не тег b.Почему em, а не i
<em> передаёт смысловое ударение (интонацию «здесь важно»), а <i> — только смену голоса: термины, названия, мысли.
<p>Я точно <em>не собиралась</em> этого делать.</p>
<p>Книга «<i>Мастер и Маргарита</i>».</p>
Маркер поиска: mark
<mark> выделяет фрагмент, актуальный в этом контексте: результаты поиска, ключевые слова, важные числа.
<p>Городу исполнилось <mark>850 лет</mark>.</p>
Мелкий текст: small
<small> — примечания и оговорки: лицензии, копирайты, сноски «условия могут отличаться».
<footer>
<small>© 2026, WebDev Уроки</small>
</footer>
Индексы и степени: sub и sup
<sub> — нижний индекс (H2O), <sup> — верхний (степени, сноски, 109).
<p>Вода — H<sub>2</sub>O. Скорость света 3·10<sup>8</sup> м/с.</p>
Код в абзаце: code и pre
<code> — код «в строке», <pre> — многострочный блок с сохранением отступов. Внутри <pre> обычно лежит <code>.
<p>Функция <code>greet()</code> приветствует.</p>
<pre><code>function greet() {
return "Привет!";
}</code></pre>
Клавиши и переменные: kbd и var
<kbd> — клавиши и команды, <var> — переменные и формулы. Оба делают инструкции «машинно-читаемыми».
<p>Нажмите <kbd>Ctrl</kbd>+<kbd>S</kbd>, чтобы сохранить <var>файл</var>.</p>
Аббревиатура с расшифровкой: abbr
<abbr> с атрибутом title расшифровывает сокращение: навели — увидели, а сам текст остаётся чистым.
<p><abbr title="Язык гипертекстовой разметки">HTML</abbr> — основа веба.</p>
Определение термина: dfn
<dfn> отмечает термин в том месте, где он впервые определяется. Словари и скринридеры распознают эту «точку определения».
<p><dfn>Гибкая вёрстка</dfn> — подход, при котором блоки приспосабливаются к ширине экрана.</p>
Цитаты: q и blockquote
<q> — короткая цитата в предложении, <blockquote> — длинная, отдельным блоком. Атрибут cite указывает источник.
<p>Он сказал: <q>всё будет хорошо</q>.</p>
<blockquote cite="https://example.ru/article">
Длинная цитата, которой нужен отдельный блок.
</blockquote>
Время: time и datetime
<time> — дата, понятная и человеку, и машине. Атрибут datetime задаёт каноничный формат.
<time datetime="2026-09-20">20 сентября</time>
Контакты: address
<address> — контакты автора документа или владельца сайта: почта, телефон, юридический адрес.
<address>
Напишите: <a href="mailto:hi@site.ru">hi@site.ru</a>
</address>
Картинка с подписью: figure
Картинку или другой автономный элемент с подписью оборачивают в <figure>, а подпись кладут в <figcaption>.
<figure>
<img src="team.jpg" alt="Команда проекта">
<figcaption>Наша команда, лето 2026</figcaption>
</figure>
Глава и разделы: section с заголовком
<section> группирует связанный контент, и каждая секция почти всегда имеет свой заголовок.
<section>
<h2>Навыки</h2>
<ul><li>HTML/CSS</li></ul>
</section>
<div>.Строительный блок без смысла: div
<div> — универсальный контейнер без встроенного смысла. Когда семантического тега нет — берут div и группируют им всё остальное.
<div class="card">
<h3>Название</h3>
<p>Описание</p>
</div>
Точечная правка: span
<span> — строчный «пустой» контейнер: им помечают кусочек текста, чтобы стилизовать или «поймать» его скриптом.
<p>Цена <span class="price">499 ₽</span></p>
<br> для «новых строк» — вероятно, нужен блочный тег.Пропуск уровня заголовка: чем грозит
Переход «h1 → h3» без h2 — как дыра в оглавлении: скринридер и поисковик видят «прыжок» иначе, а пользователь теряет иерархию.
<h1>Курс</h1>
<h3>Начало</h3> <!-- пропущен h2 -->
Как валидатор читает вложенность
Валидатор проверяет не только синтаксис, но и «где кому положено жить»: куда нельзя вкладывать, какие атрибуты лишние. Его ошибки читаются как подсказки к уроку.
Именование классов: соглашения
Имена классов — это мини-контракт: читая их, другой разработчик должен сразу понять, что за элемент. Используйте смысловые имена, а не «block1».
<!-- понятно -->
<div class="product-card">
<!-- не ясно -->
<div class="x12">
id и class: когда что выбирать
id — уникальный «паспорт» элемента (один на страницу), class — одно имя для группы. Ссылки и JS часто ищут по id, стили — почти всегда по классу.
<nav id="main-menu">...</nav>
<button class="btn">Купить</button>
<button class="btn">Заказать</button>
Булевы атрибуты: без значения
Некоторые атрибуты «работают» самим своим присутствием: required, hidden, disabled, multiple. Значение им не нужно.
<input type="email" required> <!-- включено -->
<input type="email"> <!-- выключено -->
required="required" тоже допустима, но проще писать одно слово.Кавычки в значениях атрибутов
Если внутри значения нужна кавычка — используйте другой тип: двойные снаружи, одинарные внутри (или наоборот).
<p title='Сказал: «привет»'>текст</p>
<input value='a "b" c'>
& — иначе может «поехать» соседний текст.Смешение языков с разным направлением
Слово на языке с письмом справа налево (арабский, иврит) внутри русского текста нарушает порядок. Атрибут dir и тег <bdi> отделяют такой фрагмент.
<p>Телефоны: <bdi>٣٧٥٠</bdi> и <bdi>١٢٣</bdi></p>
Шаблон, который не видно: template
<template> хранит фрагмент разметки, который не показывается, пока его не «клонируют» скриптом. Полезно для повторяющихся карточек.
<template id="card">
<div class="card"><p>Карточка</p></div>
</template>
Контент без JavaScript: noscript
<noscript> показывается только когда JavaScript отключён: запасной текст, ссылки, статичные версии компонентов.
<noscript>
<p>Включите JavaScript для полной версии сайта.</p>
</noscript>
Вопрос без ответа: details и summary
<details> — сворачиваемый блок без JavaScript, <summary> — видимый заголовок-«переключатель». Идеально для FAQ и спойлеров.
<details>
<summary>Зачем нужна семантика?</summary>
<p>Чтобы смысл читали машины и скринридеры.</p>
</details>
open раскроет блок по умолчанию, а стилизовать «галочку» поможет CSS ::marker.Дополнительный материал: aside
<aside> — контент, связанный с темой, но не обязательный: боковая колонка, заметки, «по теме», словарик по тексту.
<section>
<p>Основной текст статьи.</p>
<aside>
<p>Связанная заметка, которую можно убрать</p>
</aside>
</section>
Статьи, которые повторяются: article
<article> — самостоятельный кусок, который имеет смысл и без страницы-родителя: запись блога, новость, карточка товара.
<article>
<h2>Заголовок записи</h2>
<p>Содержимое статьи...</p>
</article>
Верх и низ: header и footer
<header> — шапка раздела (заголовок, логотип, меню), <footer> — подвал (автор, ссылки, копирайт). Они могут быть и внутри article/section.
<header>
<h1>Название сайта</h1>
</header>
<main>...</main>
<footer>
<p>© 2026</p>
</footer>
<address>. Обычный footer — для ссылок и копирайта.Навигация: что класть в nav
В <nav> живут главные маршруты: меню, оглавления, постраничная разбивка. Служебные ссылки «футер-профиля» туда класть не обязательно.
<nav>
<a href="index.html">Главная</a>
<a href="lessons.html">Уроки</a>
</nav>
aria-label = «дополнительное меню».Как скринридер «читает» разметку
Скринридер проходит по «семантической карте»: заголовки — навигация по разделам, списки — по пунктам. Div вместо тегов превращает карту в «глухую стену». Практика: включите режим виртуального курсора и слушайте собственную страницу.
Роль элемента поверх тега: role
Атрибут role меняет «роль» элемента для скринридера. Но правило простое: сперва выбирайте правильный тег, потом добавляйте ARIA, а не наоборот.
<div role="navigation">...</div> <!-- лучше: <nav> -->
Невидимые подсказки: title в разметке
Атрибут title показывает тултип при наведении. Полезно для сокращений, но не должно быть единственным источником важной информации.
<abbr title="Cascading Style Sheets">CSS</abbr>
Разметка «по смыслу»: выбор тега
Тренировка: по описанию куска текста выберете тег. «Перечень в произвольном порядке» → ul. «Шаги по порядку» → ol. «Определение слова» → dfn или dl. Не подходит ничего → div/span.
<!-- что это? -->
Продукт снят с производства в 2024 году.
Практика: страница-рецепт
Страница-рецепт — классика тренировки: заголовок, абзацы, маркированный список ингредиентов, нумерованный список шагов, время приготовления (time), примечания (small).
<h1>Омлет</h1>
<p>Готовится <time>10 минут</time>.</p>
<h2>Ингредиенты</h2>
<ul><li>Яйца</li></ul>
<h2>Шаги</h2>
<ol><li>Разбить яйца</li></ol>
Практика: карточка товара
Карточка: article, картинка figure, название h2/h3, список характеристик dl, цена, кнопка, сноска small про условия.
<article class="product">
<h3>Кружка</h3>
<dl><dt>Материал</dt><dd>Керамика</dd></dl>
<p>499 ₽</p>
</article>
Практика: запись в блоге
Запись блога: header с заголовком и датой, article с несколькими section, цитата blockquote, «связанное» в aside, footer с автором.
<article>
<header>
<h1>Как я учил HTML</h1>
<time datetime="2026-09-01">1 сентября</time>
</header>
<section><h2>Начало</h2><p>...</p></section>
<footer><address>Автор: Анна</address></footer>
</article>
Практика: FAQ из details
FAQ из details/summary не требует ни строчки JavaScript — разворачивание встроено. Добавьте по `
<details open>
<summary>Сколько длится курс?</summary>
<p>Девять уроков.</p>
</details>
<details>
<summary>Нужен ли опыт?</summary>
<p>Нет, начинаем с нуля.</p>
</details>
Проверка семантики «вслух»
Хитрый тест семантики: попросите кого-нибудь прочитать страницу «по тегам» («заголовок, список, цитата...») и сравните с вашим замыслом. Несовпадения покажут, где семантика врут.
JSON-LD вне страницы: когда нужна
Микроразметка типа JSON-LD говорит поисковику о рецепте, товаре или событии — за это появляются «звёздочки» в выдаче. Код ставится в head как отдельный скрипт.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Recipe",
"name": "Омлет"
}
</script>
Автор и права в разметке статьи
Автор — это <address> или ссылка на профиль в footer статьи; дату публикации помечайте time; про права напоминайте small.
<footer>
<address><a href="about.html">М. Иванова</a></address>
<time datetime="2026-09-20">20 сентября</time>
</footer>
Анализ чужой разметки: план действий
Разбор чужого HTML: 1) найти главный контейнер main; 2) прочитать иерархию заголовков; 3) посмотреть, что в nav/header/footer; 4) отметить лишние div; 5) спросить «какой тег здесь лучше подошёл бы».
Порядок элементов в файле: логика
Хороший HTML читается сверху вниз как изложение: шапка, навигация, главный контент, дополнения, подвал. Скрипты и стили обычно собираются в head или перед закрывающим body.
<head> <!-- мета и стили -->
<body>
<header> <!-- верх -->
<main> <!-- главное -->
<footer> <!-- низ -->
<script> <!-- скрипты -->
Язык страницы: html lang и фрагменты
Атрибут lang на <html> задаёт язык всей страницы (для скринридеров и словарей), на отдельном теге — переключает для фрагмента.
<html lang="ru">
<p>Слово можно проверить на сервисе <i lang="en">Grammarly</i>.</p>
Спецсимволы помнить наизусть
Три сущности встречаются постоянно: & — амперсанд, < — «меньше», > — «больше». Остальные символы можно не запоминать — всегда есть справка.
<p>Курс: HTML & CSS. Условие: 5 < 10.</p>
Неразрывный пробел: когда обязателен
Неразрывный пробел не даёт переносить слово на другую строку: «10 кг», «страница 5», «2026 год». Оформление не «разъедется».
<p>Купили 3 кг яблок и 5 кг апельсинов.</p>
Тире, дефис и минус: три знака
Дефис (-) соединяет части слова, тире (—) ставится в предложениях как пунктуация, минус (−) — математический знак. Раньше в вебе их путали чаще, чем хочется верить.
<p>по-русски; урок — простой; температура −5°C.</p>
Длинный текст с сохранением формы: pre
<pre> сохраняет пробелы и переносы как есть — для стихов, ASCII-схем, лог-файлов и примеров кода, где вёрстка строк важна.
<pre>Однажды,
в студёную
зимнюю пору
я из лесу вышел.</pre>
Длина абзаца и внутренние списки
Долгий абзац из восьми предложений читатели пропускают. Делите мысль: короткий абзац, затем список или пример — людям так проще «доставать» смысл.
<p>Как улучшить тексты на сайте:</p>
<ul>
<li>меньше слов на абзац;</li>
<li>больше примеров.</li>
</ul>
Заголовок, отражающий содержание
Заголовок — это обещание. Если раздел называется «Ошибки», в нём должны быть ошибки, и только. Раздел «Дополнительно» — признак того, что контент плохо сгруппирован.
<!-- плохо --><h2>Разное</h2>
<!-- лучше --><h2>Типичные ошибки вложенности</h2>
Семантические ошибки, которые не видны
Глазами текст выглядит прекрасно, но разметка врёт: список «по порядку» оформлен через ul, термин — через i, заголовок — через p. Такое не увидит ни один дизайнер, но увидит скринридер.
Проверка доступности: быстрый инструмент
Плагины в браузере (например, axe DevTools) запускаются одной кнопкой и выдают список проблем с пояснениями. «Контраст», «нет подписи у поля», «заголовок пустой» — всё это ловится автоматически.
Почему «всё из div» — это плохо
Страница из одних div работает во всех браузерах. Но её не смогут «пересказать» скринридер, поисковик и будущий вы: где заканчивается меню и начинается статья — непонятно никому.
<div class="menu">...</div> <!-- div, -->
Когда семантика реально «покупает»
Семантическая вёрстка окупается не в первый час, а в долгую: обновление чата в Кафе, перевод страниц, сниппеты в поиске, удобство для читателей на скринридерах — всё вырастает из разметки. Легко сэкономить «один вечер», тяжело потом весь срок жизни проекта.
Комментарии в разметке: за и против
Комментарии <!-- ... --> помогают ориентироваться в больших файлах, но не являются мусором: их не видит посетитель, однако файл становится длиннее. Держите комментарии короткими и редкими.
<!-- Хиро-блок: меняем под акции -->
<section class="hero">...</section>
Дублирование разметки: где опасность
Один и тот же блок (меню, карточка) скопированный пять раз — это пять мест правки. Любое изменение потом делается втройне сложнее.
<!-- одно место, код один раз -->
<nav class="menu">...</nav>
Атрибут hidden: спрятать, не удаляя
hidden убирает элемент со страницы без удаления из кода. Используется для «мобильных» блоков, попапов и условных областей.
<p hidden>Этот текст будут показывать после клика.</p>
Класс для стиля vs класс для смысла
Один класс выражает «что это» (product, menu, alert), другой — «как выглядит» (theme-dark, size-large). Ранняя привычка разделять их сохраняет CSS от хаоса.
<button class="btn btn-primary size-lg">Купить</button>
Раньше прописывали: наследие атрибутов
Старые атрибуты вроде align, bgcolor и border давно «умерли»: их обязанности перешли к CSS. В новых проектах они не нужны, но в старых сайтах встречаются — теперь вы знаете, что это такое.
<!-- было: --><p align="center">
<!-- стало: --><p class="text-center">
Список всех тегов: где искать
Никто не знает все 100+ HTML-тегов наизусть. Справочники — MDN и W3Schools; открывайте страницу тега и копируйте пример. Со временем «в голове» останется 30–40 частых.
Ошибка «забыл закрыть тег» на практике
Один незакрытый тег ломает «хвост» всей страницы: стили не применяются, скрипты не подключаются, меню едет. Браузер «терпит», но всё ломается при первом чихе.
<!-- забыли </p> -->
<p>Текст без закрытия
Разумная вложенность: глубина и хаос
Вложенность на 6–8 уровней — звоночек: вероятно, структура переусложнена. Глубина 3–4 уровня покрывает почти все реальные раскладки; простыне лучше упрощать не стилями, а разметкой.
<div class="wrapper">
<section class="card">...</section>
</div>
Тег но, который пишут все: p и div
Спор «p или div» — классика старта: p для текста, rdiv для «обёртки». Внутри p не должно быть блочных элементов; любая группа блоков — это div.
Итоги урока 2: что вы умеете
После урока 2 вы размечаете тексты и структуру: заголовки, абзацы, три вида списков, цитаты, код, время, «детали», секции и статьи, «шапки» и «подвалы», формы и их семантику. Ваша страница теперь «читается» — и людьми, и машинами.
Дальше урок 3: ссылки, изображения и таблицы. Завершите рецепт и блог — они станут «подопытными» в уроках про CSS.
Микроразметка «хлебные крошки»: BreadcrumbList
BreadcrumbList описывает «путь» страницы: Главная → Уроки → Основы. Для поиска это «карта хлебных крошек». Каждый шаг — ListItem с position и name.
<nav aria-label="Хлебные крошки">
<a href="index.html">Главная</a> /
<a href="lessons.html">Уроки</a>
</nav>
Микроразметка товара: Product и цена
В карточку товара добавляют структурированные данные Product: название, цена, доступность. Поиск может показать цену прямо в выдаче — «звёздочки» для интернет-магазинов.
<meta itemprop="price" content="1990">
<span itemprop="priceCurrency">RUB</span>
Микроразметка отзыва: Review и рейтинг
Отзыв размечают как Review: автор, текст, оценка. Рейтинг из «звёздочек» поиск может показать в результатах. Разметка «честная»: оценка должна совпадать с реальной.
Микроразметка события: Event и дата
Афиша события использует Event: название, дата, место, билеты. Схемы type не помню? Проверяйте в справочниках schema.org — там всё по полочкам.
Микроразметка организации: Organization
Раздел Organization описывает фирму: название, адрес, телефон, соцсети. Это «визитка» в поисковой выдаче — отличный старт для бизнес-сайта.
<div itemtype="https://schema.org/Organization">
<span itemprop="name">Студия «Пиксель»</span>
</div>
Микроразметка статьи: Article и автор
Статья размечается как Article: заголовок, автор, дата публикации. Поиск получает «норм метаданные» и лучше понимает, кто написал и когда обновил страницу.
<article itemtype="https://schema.org/Article">
<meta itemprop="dateModified" content="2026-09-20">
</article>
Микроразметка вопроса: FAQPage
FAQ с вопросами и ответами можно разметить как FAQPage: каждый вопрос — Question, каждый ответ — Answer. Такие страницы показываются расширенными «аккордеонами» в выдаче.
<script type="application/ld+json">
{"@type":"FAQPage", "mainEntity":[]}
</script>
JSON-LD: три поля для начала
Минимальная разметка JSON-LD умещается в три поля: @context (словарь), @type (тип), name (имя). Положить её можно прямо в head скриптом — браузер не тронет, а поиск прочитает.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Уроки веб-разработки"
}
</script>
Микроразметка без лишнего: что не размечать
Разметку добавляют туда, где она реально помогает: цена товара, афиша, FAQ. Не «засыпайте» микроразметкой каждую кнопку — это шум для поисковиков и сложность для вас.
Проверка микроразметки: валидатор Google
После разметки покажите страницу валидатору структурированных данных (Rich Results Test). Он и «распарсит» разметку, и подскажет, какие поля обязательны, а каких не хватает.
ARIA: зачем роли в HTML
ARIA «рассказывает» скринридерам, что «нарисовано» тегами: роль, состояние, свойства. Когда собственных тегов не хватает (кнопка-иконка, аккордеон), ARIA заполняет пробелы.
Роль-сообщение: role="alert"
role="alert" говорит скринридеру «сообщи срочно»: ошибка формы, предупреждение. Без фокуса читалка озвучит блок. Аккуратно: не для всего подряд, а для действительно важного.
<p role="alert">Неверный пароль</p>
Роль-статус: role="status"
role="status" — «тихое» обновление: сколько найдено, запись сохранена. Скринридер озвучит, но без срочности alert. Идеален для «живых» счётчиков.
<p role="status">Найдено 12 статей</p>
Состояние «раскрыто»: aria-expanded
aria-expanded сообщает, раскрыт ли элемент: true/false. Фиксируется на «родителе» (кнопке), меняется по клику. Так скринридер знает, меню открыто или закрыто.
<button aria-expanded="false">Меню</button>
Кнопка-иконка: aria-label вместо текста
Кнопка, где только иконка, не имеет текста для скринридера. aria-label даёт ей имя: «Поиск», «Закрыть». Инструментарий читает это имя вслух — иконка «оживает».
<button aria-label="Закрыть окно">✕</button>
Поиск-блок: role="search"
role="search" помечает зону поиска. Скринридер имеет «поиск по странице» и быстрые ссылки на такие блоки. Добавьте role на form посика — небольшая, но заметная забота.
<form role="search">
<input placeholder="Найти">
</form>
Имена для навигации: aria-label у nav
Несколько nav на странице нуждаются в различии: «Основное меню», «Нижнее меню». aria-label на nav даёт имя каждой навигации — скринридер сможет предложить их по названию.
<nav aria-label="Основное меню">...</nav>
<nav aria-label="Ссылки в подвале">...</nav>
Вкладки без JS: details и summary глубоко
details/summary — «раскрывашка» без скриптов: summary показывает заголовок, details прячет содержимое до клика. Семантика уже «в теге» — скринридер читает сам.
<details>
<summary>Как оплатить?</summary>
<p>Картой или по ссылке.</p>
</details>
Скан-чтение: как скринридер «ходит» списками
Скринридер умеет «собирать» все заголовки, ссылки, списки страницы в навигацию. Отсюда урок: абзацы и пункты списка должны «дорого» отвечать на вопрос «о чём тут».
Цвет не единственный сигнал: иконки и текст
Различать «отправлено» и «ошибка» только цветом — плохо: дальтоники и скринридеры не увидят. Добавьте текст или иконку. Сигнал «в дубле» = сигнал доступный.
Типографика: кавычки «ёлочки» на практике
Русская типографика любит «ёлочки» (<< >>), внутри — «лапки». На клавиатуре их нет, поэтому в HTML их вводят или сущностями, или просто копируют готовые символы из текста.
«ёлочки»
„лапки“
Типографика: тире длинное и короткое
Длинное тире «—» ставится между частями предложения, короткое «–» — в диапазонах (2026–2027). Дефис «-» — внутри слов. Разные символы несут разные смыслы.
Урок — это практика.
Цены: 2026–2027 гг.
front-end‑разработка
Скобки и вложенность: «своё» и «чужое»
Скобки внутри текста — «( ), [ ], { }» — лишь персонажи. В математике и списках у них своя роль. Размечать их HTML-тегами не нужно: они рабочие символы текста.
Неразрывный пробел: когда он обязателен
Неразрывный пробел удерживает слова «вместе» при переносе строки: «т. д.», «10 000₽», «г. Москва». Без него браузер унесёт «₽» на новую строку, но имел в виду пару «10 ₽».
Стоимость: 1 500 ₽
Слоговые переносы: словарные
Wbr — «место, где можно перенести». Внутри wbr браузер может переставить строку, если не влезает. Полезно для длинных URL и слов без естественных разрывов.
супермаркетисточникданных
Ширина строки: 45–75 символов абзаца
Читать удобно, когда в строке 45–75 символов: глаза «не теряются». Длинные абзацы целой страницы — чтение по диагонали. Это касается и текстов сайтов, и ваших комментариев в коде.
Абзацы читаются: ритм вёрстки
Один абзац — одна мысль. Два абзаца, говорящие «одно и то же», ужимаются в один. Ритм «короткий–длинный» удерживает внимание лучше ровного «потока воды».
Иноязычный фрагмент: lang и курсив
Слово на другом языке внутри русского текста помечают и lang="en", и смысловым курсивом: design. Скринридер прочитает его «по-английски», словно с акцентом.
<p>
Понял <span lang="en">maintain</span> значит «поддерживать».
</p>
Числа и единицы: 15 км в разметке
Число и единицу измерения люди читают вместе. Размечать их отдельно не обязательно, но в «машинном» контексте (прогноз, статистика) единицу дают как данные. Проявляйте согласованность: метрики — метриками.
Даты и время: datetime формат ISO
Тег time с datetime имеет машиночитаемый формат: 2026-09-20T14:30. Расшифровка: год-месяц-день T время. Так помощники и поиск понимают дату без догадок «20 сентября».
<time datetime="2026-09-20T10:00">
в субботу утром</time>
Карточка товара: анатомия семантичных блоков
Карточка товара — мини-документ: заголовок, картинка, описание, цена, кнопка. Разметка «по смыслу»: article для карточки, figure для фото, dl для параметров, button для покупки.
<article class="card">
<h3>Наушники «Тишина»</h3>
<p>Беспроводные, белые.</p>
<button type="button">В корзину</button>
</article>
Заголовок карточки: h2 или h3
Заголовок карточки зависит от уровня секции: если карточка в разделе h2 — в ней h3; если страница «вся сетка карточек» — каждая может начинаться с h2. Без «пропусков» уровней.
Ссылка «подробнее»: но с описанием
Ссылки-анонсы «Подробнее» никто не любит: непонятно «куда». Сделайте текст осмысленным — «Читать обзор наушников» — или добавьте aria-label с названием раздела, куда ведёт.
<a href="review.html">
Читать обзор целиком</a>
Кнопка-ссылка на карточке: так правильно
«Купить» и «Читать» на карточке — это переход, значит тег , а не button. Кнопку оставляют действиям: «Добавить в корзину», «Голосовать». Ссылка ведёт — кнопка действует.
Аватары и подписи: figure в профилях
Аватар с именем — тандем figure и figcaption: «изображение + подпись». Подпись живёт рядом и «привязана» к картинке, скринридер читает её вместе.
<figure>
<img src="user.jpg" alt="Фото автора">
<figcaption>Анна, автор курса</figcaption>
</figure>
Список функций: ul без маркера
Перечисление возможностей логично быть списком ul — даже если маркеры потом скрыты CSS. Смысл «набор пунктов» сохраняется: скринридер озвучит «список из трёх пунктов».
<ul>
<li>Турбо-режим</li>
<li>Тихое охлаждение</li>
</ul>
Контакты в подвале: address против p
Для контактной информации ближайший тег — address: телефон, адрес, почта «в одном месте». Для «случайного» абзаца с реквизитами годится p, но контакты — это address.
<address>
г. Москва, ул. Примерная, 42
</address>
Логотип семантично: img с alt или svg
Логотип в шапке выполняет роль «ссылка на главную». Картинку делаем ссылкой — или встроенным SVG: он масштабируется и «легчает».
<a href="index.html">
<img src="logo.svg" alt="Студия «Пиксель»">
</a>
Доп. кнопки: small-подпись
Кнопка с оговорённой мелкой подписью — например, «Условия», «Последний срок»: small внутри button или рядом. «Мелочь» со смыслом, которую скринридер прочитает отдельно.
«Читать далее»: анонс в карточке
Анонс «Читать далее» вежливее: первый абзац текста на странице статьи + ссылка «дословно на саму статью». Так читатель понимает «о чём», а не «где кнопка».
<h3>Как наладить сон</h3>
<p>Советы, которые проверены лично...</p>
<a href="sleep.html">Читать статью</a>
Длинная страница: оглавление и якоря
Для длинного материала нужна «точка входа»: оглавление с якорями. Ссылки ведут к id заголовков; после клика скрипт или CSS подсвечивают текущую секцию — навигация «живая».
<nav>
<a href="#favs">Любимые приёмы</a>
</nav>
FAQ-блок: применённые details
Вопрос-ответ «в один клик»: details/summary. Каждый вопрос — summary, ответ — контент details. Никакого JS: раскрытие работает в каждом браузере из коробки.
<details open>
<summary>Сколько длится курс?</summary>
<p>Девять уроков, в своём темпе.</p>
</details>
Иерархия практикой: глава/раздел/подраздел
Чем глубже материал, тем «глубже» заголовки: h2 — глава, h3 — раздел, h4 — подраздел. Неприкосновенное правило: не перескакивайте уровень «вверх» без причины.
<h2>Основы</h2>
<h3>Теги</h3>
<h4>Строчные</h4>
Шаблон блога: структура поста
Пост в блоге бьётся на: статья (article), заголовок, дата (time), вступительный абзац, тело текста, контакты автора. Опишите это один раз — дальше копируйте «скелет» на все посты.
Шаблон «Контакты»: проверенные блоки
Контактная страница складывается из проверенных блоков: заголовок, адрес (address), телефон и почта ссылками, схема-карта, форма. Ваша страница — «очередная», но каждая удобна одинаково.
Заголовки и поиск: индексация структуры
Поисковые системы строят «аннотацию» страницы по заголовкам.h2 с осмысленными вопросами («как починить...», «почему...») попадают в расширенную выдачу. Структура = «карта знаний».
Норма вёрстки: валидность против читаемости
Валидность — «браузер не спотыкается». Читаемость — «человек понимает». Иногда идеальная валидность проигрывает практичности: начните с валидного, а «удобнее-но-с-оговоркой» оставляйте на потом.
Ссылки-звенья: связка тегов внутри
Термин в тексте может быть ссылкой на его описание: <a href="#def">див</a>. Так «звенья» текста складываются в сеть знаний — как в википедии.
Строка меню: strong против b в навигации
В активном пункте меню жирный текст уместен. Его делает strong (смысловое ударение на «вы здесь»), но чаще это CSS. Для «вы здесь» хватает класса и атрибута aria-current="page" — никаких extra b.
<a href="#lessons" aria-current="page">
Уроки</a>
Якорные заголовки: id для h2 глубоко
id у заголовков делает их целями ссылок-якорей: #oi может быть id="oi" у h2. Если название «короедское», дайте якорю id, а в ссылке используйте этот «машинный» адрес.
<h2 id="faq-price">Сколько стоит курс</h2>
<a href="#faq-price">про цену</a>
Практика: страница «рецепт» с микроразметкой
Соберите рецепт: article с заголовком, списком ингредиентов (ul), шагами (ol), временем (time). Добавьте микроразметку Recipe — и это будет «оживлённый» пример сразу с пользой для SEO.
<h1>Блины на молоке</h1>
<ul>
<li>Молоко — 500 мл</li>
</ul>
Практика: карточка товара с ARIA
Добавьте доступность к карточке: aria-label у иконки-кнопки, aria-expanded у «раскрыть описание», состояние «в корзине» через aria-live. Мини-макросы ARIA превращают карточку в «дружелюбный» интерактив.
Практика: блог-пост полный свод правил
Соберите пост по всем правилам: единственный h1, дата в time, цитаты в blockquote, списки для перечислений, автор в address, ссылки «с понятным текстом». Всё — без стилей, только семантика.
Практика: FAQ с details и микроразметкой
Вопросы-ответы через details/summary плюс JSON-LD FAQPage: готовый «аккордеон» с расширенным поиском. Один блок — две выгоды: удобный контент и «продвинутая» выдача.
<details>
<summary>Где смотреть результаты?</summary>
<p>На странице вашего профиля.</p>
</details>
Итоги урока 2: чек-лист семантики
Чек-лист: тег «по смыслу», а не «по виду»; один h1 и ровная иерархия; списки для перечислений; цитаты и время — смысловыми тегами; формы с label; alt у картинок; lang проставлен; микроразметка там, где она решает.
Аудит семантики: 4 шага
Аудит за 4 шага: выключите CSS (Ctrl+Shift+P — «Emulate CSS disabled»); прочитайте страницу «сверху вниз»; отметьте, где структура «развалилась»; верните стили и «почините» смысл. Чистка запутанного HTML успокаивает.
Частые ошибки семантики: 5 штук
1) свой h2 без h1; 2) div вместо ul для перечислений; 3) кавычки «ёлочкой» через HTML-сущности «на память»; 4) картинки без alt повсюду; 5) span вместо p для абзацев. Увидели — сразу правьте.
Прогрессия: от div к осмысленному
Путь новичка: «всё из div» → «что-то из section/article» → «тег по смыслу от корня». На каждом шаге страница становится доступнее. Не осуждайте «дивы»: важно направление роста.
Рефакторинг: превращаем div в section/article
Рефакторинг: замените div на section там, где есть заголовок; на article — где «самостоятельный блок»; на header/footer/main/nav/aside — где очевидно. Обновите классы «по смыслу», перечитайте.
<div class="block"> <!-- было -->
<section> <!-- стало -->
<h2>Услуги</h2>
</section>
Финальное задание: сверстать «справочник тегов»
Сделайте страницу-справочник: введите 20 знакомых тегов, у каждого — описание и пример в code. Пока вы пишете содержимое, вы «читаете» теги заново. Итог: шпаргалка, которая всегда под рукой.
Семантика как «язык» страницы
Семантические теги — «слова» единого языка: заголовок, список, цитата, навигация. Браузер, поиск и скринридер «понимают» их одинаково. Чем «чище» разметка — тем легче «диалог» всех участников.
Секция и её заголовок: связка по правилам
Раздел начинается с заголовка: h2 после открывающего section. «Пустая» секция «без» заголовка «сбивает» оглавление. Одна секция — «один» заголовок — «одна» тема.
<section>
<h2>Наша команда</h2>
<p>...</p>
</section>
Article внутри статьи: вложенные «публикации»
Article может «жить в» article: комментарии внутри записи, цитата-статья внутри обзора. «Содержимое элемента» — «самостоятельный» материал. Вложенность — по «логике», не «для красоты».
Aside: контент «в сторону» от основного
Aside — боковая «приписка»: справка, цитата, блог-виджет. «Связанно», но «отстраняется». Внутри статьи — «врезка»; вне — «сайдбар» сайта. Разделяет «главное» и «дополнительное».
Footer: не только «подвал страницы»
Footer «закрывает» раздел: подпись, автор, «связанные» ссылки. У статьи — «свой» footer (автор, дата), у страницы — «общий». Тег «переносим»: footer «внутри» section — законно.
Порядок и размер заголовков vs смысл
Оголовок «не про размер»: h3 может «выглядеть» крупнее h2 (стилизация CSS). Смысл — в «уровне» иерархии. «Больше-меньше» — дело стилей; «выше-ниже» — дело разметки.
Оглавление из заголовков: навигация «по уровням»
Заголовки всех страниц образуют «оглавление». Скринридер «перемещается» по H-тегам, как по меню. «Прыжки» уровней «подпрыгивают» и читателя. Стройте «лестницу» без ступеней-«скачков».
Лента новостей: article как единица потока
Список записей — «серия» article: заголовок, абзац, ссылка «читать». Повторяемая «карточка» = повторяемый article. Поток «новостных» элементов «читается» семантикой «карточки».
Образа навигации: nav против «всех ссылок»
nav — «главные» блоки ссылок: меню сайта, «постраничная» навигация. Не обертывайте «каждую» ссылку текста в nav: перегрузите «карту». «Маленькая» справка-ссылки в nav — «без смысла».
Main: «главная» зона документа
main — «центральное» содержимое страницы, «одно» на документ. Шапка, подвал, сайдбар — «вне». Скринридер «прыгает» в main «мимо меню». «Связка» страниц — «общие» блоки вне main.
Микроразметка против JSON-LD: два подхода
Микроразметка живёт «в» тегах (itemscope, itemprop), JSON-LD — «отдельный» блок <script type="application/ld+json">. JSON-LD «не трогает» видимый HTML — меньше «риска поломки». Выбор — «по удобству» команды.
Метки микроразметки: itemscope и itemprop
itemscope «открывает» элемент-объект; itemprop «называет» свойства. «Товар» — itemscope; «название», «цена», «рейтинг» — itemprop. Иерархия «объект→свойство» — как «вложенные» словари.
<div itemscope itemtype="https://schema.org/Product">
<span itemprop="name">Кроссовки</span>
<span itemprop="price">5900</span>
</div>
JSON-LD: карточка товара в голове
Блок JSON-LD «Product» рассказывает про товар: название, цену, доступность. Поиск «строит» расширенную выдачу «из» него. Примеры: «цена», «наличие», «рейтинг» — полезные свойства.
<script type="application/ld+json">
{"@context": "https://schema.org", "@type": "Product", "name": "Кроссовки", "offers": {"@type": "Offer", "price": "5900", "priceCurrency": "RUB"}}
</script>
Recipe JSON-LD: рецепт в выдаче
Schema Recipe «описывает» блюдо: название, ингредиенты, время, калории. Поиск показывает «карточку блюда» — минуты выигрыша «у конкурентов». Ингредиенты — «имя» каждая единица.
Organization JSON-LD: фирма и её логотип
Schema Organization — «имя», «логотип», «контакты», «соцсети». В выдаче — «знакомый» бренд-блок. Компаниям «стоит» разместить «частичку» на страницах контактов.
Person JSON-LD: автор и карточка личности
Schema Person на «странице автора»: имя, роль, ссылки, фотография. Личные бренды — «поисковая визитка». Свойства name, jobTitle, url, image — «стартовый набор».
Breadcrumb JSON-LD: «хлебные крошки» в выдаче
Схема BreadcrumbList отражает путь: Главная > Раздел > Страница. В выдаче — «крошки» под статьёй: «куда» ведёт страница. itemListElement — «по позиции» позиции пути.
FAQ JSON-LD: вопросы-ответы для расширенной выдачи
FAQPage «массив» вопросов и ответов → в выдаче «раскрывающиеся» строки. «Частые» вопросы «находятся» быстрее. Не «раздувайте» — главное «пользуйтесь», «без спама».
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Сколько длится курс?","acceptedAnswer":{"@type":"Answer","text":"Около месяца."}}]}
</script>
Event JSON-LD: афиша мероприятия
Schema Event для концерта/вебинара: название, дата, место, билеты. В выдаче — «событие» с «купить». startDate — ISO; location — PostalAddress или VirtualLocation.
Video JSON-LD: видео в поиске
VideoObject: «имя», «описание», «длительность», «миниатюра», URL. Видеоцитаты — «расширенная» строка. thumbnailUrl — картинка «превью»; duration — ISO «PT15M».
ARIA: когда она «не нужна»
Нативные элементы «говорят сами»: button — уже «кнопка», nav — уже «навигация». Дублировать роль ARIA «на родном» теге — лишнее. ARIA «включается», когда «своего» тега или «свойства» не хватает.
aria-labelledby: подпись из другого места
Свойство «ссылается» на id другого элемента: подпись «глазами» берётся оттуда. Диалог с заголовком, поле «привязанное» к тексту. «Подпись» переиспользуется без «дублирования» текста.
<div id="t">Окно сообщения</div>
<div role="dialog" aria-labelledby="t">...</div>
aria-describedby: описание-примечание
Дополнительная справка: «к полю» — «подсказка», «дальше» — «уточнение». Скринридер «читает» после «имени поля». Отличие от aria-labelledby: «основное имя» против «вспомогательного объяснения».
Невидимость для скринридера: aria-hidden в деле
aria-hidden="true" «прячет» элемент от чтения: декоративную иконку, «дублирующую» надпись. «Видимый» контент «остаётся» видимым — «эффект» только «для слуха». Не прячьте «важное подсказки».
Живой регион: aria-live и обновления
Когда «часть» страницы меняется скриптом — читатель «не заметит». aria-live="polite" — «сообщать» после текущей речи, "assertive" — «срочно». Статусы «отправлено», «загрузка…» — «его» работа.
Списки в ARIA: role list и listitem
Если «внешние» списки «сделаны» div-ами — role="list" и role="listitem" возвращают «структуру». Для «настоящего» ul это не нужно. «Только» для «нестандартных» конструкций.
Меню в ARIA: role menu и menuitem
«Прикладные» меню у приложений — role=menu/menuitem с клавиатурой. На сайтах «выпадашки» — чаще «навигация»+ссылок, а не «меню приложения». Не «называйте» site-навигацию словом «menu» без нужды.
Вкладки в ARIA: роли tab, tablist, tabpanel
Вкладки «скрывают-показывают» панели: tablist «ряд», tab — «заголовок», tabpanel — «содержимое». aria-selected — «активность». Клавиатура: стрелки «переключают», Tab — «в панель».
<div role="tabpanel" aria-labelledby="tab1">...</div>
Диалог: role dialog и его фон
Модальное окно — role="dialog" с aria-modal="true": контент «снаружи» — «в тени». aria-labelledby — «заголовок» окна, «фокус» «внутрь» при открытии. Закрытие по «Esc» — «этикет» диалогов.
Роль presentation: «снять» семантику
role="presentation" «гасит» смысл элемента: «таблица-разметка» читается «строками», «декоративная» группа — «молча». Используйте «рядко»: когда «сам» элемент «ничего не значит» для чтения.
Кавычки: «ёлочки» против «лапок»
Для русского текста «правильные» кавычки — «ёлочки»: « » в тексте, „лапки" для «в кавычках». HTML-сущности « » дают аккуратные «ёлочки». Не «рисуйте» кавычки «двумя грудами» («) — «машинописные» «некрасивы.
Тире длинное: как правильно «—»
Длинное тире (—) разделяет части предложения; короткое (–) — «диапазоны»: 10–20. — и – — сущности. Не «подменяйте» тире дефисом (-): «разница» читается и «машине», и «человеку».
Дефис и минус: не путайте знаки
Дефис (-) соединяет «слова»; минус (−) — в формулах и числах. «Полу-лист», «-5°» — разные знаки. В HTML «-5°» — U+2212 или «—»? Нет: корректный минус — «минус-символ» −, а не дефис.
Инициалы и годы: «неотрывные» связки
«П. И. Смирнов» и «2025–2026» «не должны» разрываться на переносе. Неразрывный пробел ( ) держит «связку». «Единые» пары: номер-единица, инициалы-фамилия, «год-тире-год».
Курсив: «итальянское» начертание и его смысл
Курсив «замещает» иноязычные слова, названия, термины: i, em. Смысловой акцент — em; «типографика» — i. Не «курсивите» «целые» абзацы: «читабельность» падает, «смысла» нет.
Читаемость: длина строки и интервал
«Удобная» строка — 45–90 символов; интервалы — «воздух» между строк. Текст «в столбик металлом» «устаёт» глаз. Эти «настройки» — CSS (max-width, line-height); разметка лишь «структурирует».
Многоточие: «…» вместо «точек»
Многоточие — «один» знак … (или «…»), а не «три точки». «Передумал…» и «ещё не всё» — «пауза». Не «ставьте» пробел перед … в «середине» слова: «он… и». Правильно «он… и» — вместе.
Числа и дроби в тексте
«Тысячи» — без «пробелов-точек групп»: 12 500 (с ). Дроби — «1/2» текстом или «дроби-символы» (½). «Целые» числа с единицами — «неотрывной» пареей. «Локализация» «выбирает» разделители.
Ссылка и пунктуация: где точка
Точка «после» ссылки — «вне» (не кликабельная); нужная «часть» фразы — «внутри» ссылки. «Читайте» «до» и «после»: точка не «входит» в адрес. «Правило»: знаки препинания — «за» ссылкой.
Типографика за пять минут: чек-лист
Проверьте за 5 минут: «ёлочки» в кавычках; «—» длинное тире; «–» в диапазонах; « » в связках; «…» многоточие. «Авто-типографика» «с помощью» сервисов — «для» больших текстов.
Заголовки и поиск: якоря выдачи
Поиск «показывает» заголовки в выдаче и использует их «смысл» для контекста. h1 — «тема страницы», h2 — «срезы» темы. «Честные» заголовки — «отыскать» страницу проще. «Настоящий» текст, а не «ключи-шапки».
Опыт и доверие: сигналы глубокого контента
Поиск «ценит» авторитетность: авторы, источники, даты, обновления. article + time и address автора — «сигналы» «доверия». «Кто написал», «когда», «по каким источникам» — размечайте.
Внутренние ссылки: связность страниц
Страницы «связаны» ссылками друг с другом: «смежные» статьи, «вверх по разделу». Поиск «ходит» по ссылкам — «находит» новые страницы. «Смысловые» ссылки «в тексте» — «полезные» для читателя и «для паука».
Title и выдача: «строка» клика
Title — «главный» текст в выдаче: «кликают» по нему. Структура «слово-подчерк»: Раздел — Подраздел — Бренд. «Дублирование» title у «много» страниц — «размывает» выбор.
Meta description: текст под ссылкой
description — «описание» страницы в выдаче (поиск может «сам» составить). «Продающая» строка из 150–160 символов «поднимает» клики. Содержит «пользу», а не «набивку ключей».
<meta name="description" content="Научитесь вёрстке: 9 уроков с практикой и примерами кода.">
Канонический адрес: главная версия страницы
Один и тот же контент на «нескольких» URL (категория, фильтр) — link rel="canonical" говорит «главную». Поиск «склеивает» дубли и «передаёт» вес. Дата «страницы-релизов» — относилась к «канону».
<link rel="canonical" href="https://site.ru/kurs/">
Картинки и поиск: alt и имя файла
Поиск «читает» alt, имя файла и контекст картинки. «Картинка-товар» с alt="красные кожаные туфли" — «находится» в картинках. Не «набивайте» alt «словами-повторами»: «смысл» важнее «плотности».
Расширенная выдача: куда «целиться»
Расширенные результаты: рецепты, товары, FAQ, события — «из» разметки. Ни одна страница «не обязана» «показываться» расширенно, но «шанс» выше с разметкой. «Схема» под «свой» формат — «ваш билет» в «отличную» выдачу.
Не индексировать: meta robots noindex
Страницы «вне» поиска: спасибо-страницы, дубли, черновики — meta robots="noindex". «Служебное» — «не выставлять» в выдачу. Ссылки на «noindex» «не передают» «вес», но «ходят» пауки.
<meta name="robots" content="noindex, nofollow">
Практика: SEO-чек-лист страницы
На «любой» странице: 1) h1 «один и тематический»; 2) title «до 60»; 3) description «уникальный»; 4) alt «у картинок»; 5) «внутренняя ссылка» «на соседа». Пять пунктов — «быстрая» гигиена.
Доступность: кому она нужна
Доступность — «не» «для избранных»: зрение, слух, моторные «особенности», «старение» — временные «обстановки». Свет на улице, шум, «одна рука» — «тоже доступность». «Дизайн для всех» — «выгода всем».
Контраст: текст «на фоне»
Контраст «между» текстом и фоном должен «обеспечить» читаемость: WCAG «рекомендует» 4.5:1 для текста. «Жёлтый на белом» — «низкий», «короткий» «тусклый» текст — «нечитаем» для многих. «Проверяйте» инструментами.
Видимый фокус: «где я сейчас»
Фокус «показывает» текущий элемент при клавиатуре: заметная рамка outline. Если из «своих» стилей «убрали» outline — фокус «потерялся». «Красиво» и «заметно» — «совместимы»: не «убирайте» индикатор.
Скринридер: как «слышится» страница
Скринридер читает «структуру»: роли, заголовки, alt, label — «вслух». «Порядок» чтения — «по DOM». «Музыку» «слышит» пользователь: «испытайте» свою страницу — «глазами» «меняются» на «уши».
Клавиатура: всё «без мыши»
«Все» действия «доступны» с клавиатуры: Tab, Enter, пробел, стрелки, Esc. «Мышь» — «не обязательна»: «hover»-эффекты «не» «действие». «Проверьте»: дойдите до «всех» функций «слепо» по Tab.
Медиа «альтернативно»: текстовые пары
Картинка — alt; видео — субтитры и «транскрипт»; аудио — «стенограмма». «Текст» «вместо» медиа «доступен» всем. alt «описывает», а «пустые» — «декоративные». «Дубликат» «лёгкий» — «не повредит».
Движение: «сниженная» анимация
Пользователи «с» вестибулярными «особенностями» «не любят» «агрессивные» движения. prefers-reduced-motion в CSS «отключает» анимации по запросу. «Параллакс», «карусель-авто», «мерцание» — «ослабляйте».
Атрибут lang: «голос» и «перевод»
lang «на корне» — «язык» страницы для озвучки и правописания. «Вставка» «иностранного» слова — lang на «внутреннем» элементе. «Без языка» скринридер «читает» «неправильным» акцентом.
Доступные формы: label, ошибки, фокус
Форма «доступна», когда: поля «с» label, «ошибки» — текстом рядом и в aria-live, фокус «на первом» неверном. «Красный» цвет «не» «единственный» сигнал: «всё» «текстом». «Проверяйте» «пути» «Tab».
Аудит доступности: инструменты проверки
«Автоматическая» проверка: Lighthouse, WAVE, axe. «Глазами» «и» «клавиатурой» — «тоже» аудит. «Автомат» «находит» «половину»: «руки» «добивают» «остальное». «Делайте» «аудит» «постоянно».
Практика: каркас полноценной статьи
Соберите статью «по полному каркасу»: header с h1 и временем, main с section, aside-«врезку», footer к статье, «общее» — главный footer. Читайте «структуру» глазами: «голова-тело-подвал» видны.
Практика: каталог из article-карточек
«Каталог» — список article: thumb, название, описание, цена, ссылка. ul>li>article — «структура» «единиц». «Микроразметка» Product «на каждой» — «поисковая» выдача. «Карточка» «самодостаточна».
Практика: FAQ с JSON-LD в DOM
details+summary «в» панели «раскрытия» + соответствие «вопросы-ответы» в FAQPage JSON-LD. «Лёгкий» интерактив «без» JS + «расширенная» выдача. «Контроль» «согласия» текста «страница-схема».
<details>
<summary>Сколько длится курс?</summary>
<p>Около месяца.</p>
</details>
Практика: страница-профиль с Person
«Профиль» «человека»: фото (figure), имя (h1), роль, контакты, «о себе». JSON-LD Person «перекликается» «с» «полями». «Схема» и «видимое» — «одно целое», «не» «разъезжается».
Практика: хлебные крошки с breadcrumb
nav>ol>li — «крошки на виду»; баттоп BreadcrumbList*li*article — «крошки в выдаче». position: 1 «главная», дальше «по уровням». «Крошки» «связывают» «иерархию» страницы.
Практика: афиша события с Event
«Афиша» «мероприятия»: дата (time), место (address), описание, билеты. JSON-LD Event: startDate, location, offers. «Афиша» «в выдаче» «притягивает» «тематический» «трафик».
Проверка схемы: валидатор разметки
Два «валидатора»: HTML (w3.org) и Схема (Google Rich Results). Первый — «синтаксис», второй — «структурированные данные». «Ошибки» — «в панели», «исправьте» «и» «пересдайте». «Инструменты» — «не враги».
«Слепой» тест понятности
«Выключите» CSS на странице (в DevTools) и «прочитайте»: «логика» «по порядку»? Заголовки «в иерархии»? Формы «подписаны»? «Без» «красоты» «видна» «суть структуры». «Тест» — «за минуту».
Эволюция разметки: пять шагов к чистоте
1) «Нач» с div «жизнь»; 2) «замените» «заголовки-зоны» — header/main/footer; 3) «разделы» — section/article; 4) «добавьте» «смысл» спискам и «медиа»; 5) «обогатите» «данными» (разметка). «По шагу» за «урок» — «чисто» «незаметно».
Рефакторинг: большая «разметка» мастер-проекта
«Возьмите» любую «страницу» и «переведите» в «чистую» семантику: «заголовки-лестница», article, nav, микроразметка. «Послушайте» скринридером, «прогоните» валидаторы. «Крупный» «заказ» — «итог» урока 2.
div-страница против семантической
«Дивная» страница — сплошные div и классы; семантическая — значимые теги по месту. Обе выглядят одинаково, но читаются по-разному. Выбор — не о дизайне, а о смысле.
section и article: границы смысла
section группирует по теме; article — самостоятельный материал. article с section внутри — статья, разделы которой — section. Критерий: самостоятельность. Спросите «можно ли вынести» — да = article, нет = section.
Header: у страницы и у секции
header — вступительная зона содержания: может жить в section, в article, на странице. На странице — бренд-блок; в секции — её вводная. header содержит заголовок, но сам заголовком не является.
Группировка: свои обёртки по смыслу
Недостающие обёртки — промо-блок, пара «метка-значение» — делаются div с классом. Нет стандартного тега — div + класс честный выбор. Свой смысл — в данных и стилях, не в «изобретении тега».
Порядок: nav до или после контента
«До» — навигация раньше контента в DOM; «после» — контент впереди для чтения. Единого правила нет: контекст решает. Кросс-ссылка «к main» сглаживает любой порядок.
div — рабочий контейнер раскладки
div бессмыслен сам по себе, но незаменим в раскладке: ряды, сетки, обёртки. Семантический тег сильнее, когда есть смысл; div — когда смысла нет. Не стесняйтесь: без div раскладку не собрать.
Валидный не значит осмысленный
Валидатор одобряет любые закрытые теги; осмысленность — в голове автора. h1 для логотипа валиден, но нелогичен. Инструменты не выясняют намерения. Смысл — ваше решение.
Доступность и SEO: общий корень
Доступность и SEO любят семантику: заголовки, alt, разметку, осмысленные ссылки. Оптимизация для поиска не вредит доступности. Два мира — одна разметка. Красивое совпадение.
Спецификация: стандарт как ориентир
HTML живет по спецификации WHATWG/W3C: документы, новые теги, атрибуты. Работа по стандарту — предсказуемость во всех браузерах. Хаки устаревают быстрее, чем правило.
Семантика как документация для людей
Имя тега рассказывает коллегам: здесь article, тут nav, это footer. Код читается смыслом сам, без комментариев. Семантика — документация, которую нельзя забыть обновить.
Итоги: семантические кирпичи целы
Урок 2 собрал «кирпичи» смысла: section, article, aside, header, footer, nav, main. Разметка теперь «объясняет» страницу, а не просто «показывает». Структура — основа всего дальнейшего.
Мост к стилям: от смысла к виду
Семантика готова — начинается оформление: CSS будет «одевать» заголовки, списки и карточки. Прицепите стили к классам и тегам смысловой структуры. Урок 3 — первые CSS-правила.
Типичные ошибки семантики: список
Частые промахи: div вместо заголовков, h1 не один, секция без заголовка, путаница section/article, весь текст в b/i. Каждая ошибка — «дырка» в структуре.
Закрепление: главные теги наизусть
Двадцать тегов урока: article, aside, blockquote, details, dl, fieldset, figure, footer, header, main, nav. Плюс микроразметка и ARIA. Знание «на память» ускоряет вёрстку вдвое.
Домашнее задание: страница-анкета
Соберите анкету участника: fieldset-группы, radio-выбор, checkbox-интересы, textarea, обязательные поля, JSON-LD (если уместно). Встречайте хуки: label для каждого поля.
Типографика на практике: лайфхаки
Быстрая типографика: «ёлочки», —, –, …, . Настройте автозамену в редакторе — типографика «чинится» на лету. Сервисы-типографы для больших текстов — ваши помощники.
Контрольная: страница по спецификации
Соберите «корпоративную» страницу: шапка, навигация, article с афишей (Event), продуктовый каталог (Product), футер. Проверьте валидность, контраст, Tab-порядок, JSON-LD.
После урока: ресурсы для семантики
Полезные ресурсы: спецификация HTML, словарь schema.org, инструменты валидации и аудита доступности. Изучайте «по потребности»: наткнулись на тег — прочтите доку.
Скорость: семантика не тормозит
Семантические теги не «тяжелее» div: парсер справляется, кэш и рендер не страдают. Смысл не увеличивает вес страницы. «Чистая» структура даже помогает в читаемости кода.
Заключение урока 2: понимание есть разметка
Смысл — в тегах: научившись размечать по смыслу, вы научились «читать» сайты изнутри. Урок 2 дал язык для всех следующих. Дальше — как этот смысл одеть в стили.
Наследование цвета: почему текст вдруг стал голубым
Наследование — «память» цвета от родителя: p «унаследует» color от body. Убрали цвет «у» body — абзацы «сами» стали «потемнее». Cвойство наследуемое — font-family, color, line-height. Не наследуемое — margin, padding, border. Скринридер не «в» своём отражении читает цвет — «смысл» текста тот же. Закон: некоторые общие установки капают вниз, как вода сквозь землю. Нарушая наследование — думайте «почему». Полезно: цвет «по умолчанию» в body = каскад-ядро.
Каскад под микроскопом: источник и порядок
Каскад — «правило голосования» CSS: кто важнее? Сначала — источник (автор vs пользователь vs UA), потом — специфичность, потом — порядок. Авторские стили «бьют» браузерные. Пользовательские могут « взять верх». !important — «громкий голос» из-за очереди, используйте редко. Калькулятор специфичности — not лишний (id/class/тег). Итог правила: у каждой «войны стилей» есть строгий судья. Понять каскад = понять CSS целиком. Не пишите вслепую, «взвешивайте».
Специфичность: почему .btn сильнее button
Специфичность считает: id (100) > class/attribute/pseudo-class (10) > tag/pseudo-element (1). <button class="btn"> — CSS button{...} проигрывает .btn{...}. Не гадайте — считайте. Вложенный селектор .card p = 11. Почему inline style «всегда» бьёт — потому что специфичность высшая. Подход: меньше id в селекторах — проще переопределять. Калькулятор спец — ваш рефлектор. Если правило не применилось — проверьте специфичность, а не «обновляйте» отчаянно. Дисциплина каскада — дыхание стилей.
Итого про единицы: почему rem главный дружок
em — вдвое: margin-right: 1em «внутри» p с font-size 20px = 20px. rem всегда от размер шрифта <html>, em — от текущего. rem «мирится» с масштабированием пользователя, em «накапливается» во вложенных. В установках доступности крупный шрифт — rem вырастет, em может «раздуться». Правило базовой практики: размер текста — rem, отступы — rem/em по вкусу, px для границ в 1px. Изучите чувство: rem — «стабильно вложенный» шаг. Путаница исчезает при практике. Двигайтесь: rem вы правы.
margin: auto как центровщик
margin: 0 auto — «сам» центрирует блочный элемент с заданной шириной (width или max-width). Лево/право «поделят» свободное пространство поровну. Только горизонтально (auto по вертикали не работает без flex). <div class="container"> с width + margin auto — классика. Не «центрируйте» так inline — для текста text-align. Ось «x» — простая математика, ось «y» — другая история. Попробуйте: width 60% + margin auto. Разве не магия? Учите «авто-отступ» — базовый инструмент колонок.
italic-курсив: как попросить наклон
font-style: italic — «наклон» текста. italic vs oblique — большинство браузеров реально показывают один и тот же снимок. Курсив реально есть не у каждого шрифта — может «фабриковаться». em тег — семантический акцент, CSS italic — просто вид. Не путайте: скринридер не «наклоняет» голос из-за CSS. Для стихов и мыслей italic «уместен». Цитаты в кавычках совсем стихотворной роли не требуют италика. Сделайте абзац italic и посмотрите на курсивные края — элегантность. «Курсив зажмурился».
Утолщение: font-weight и доступный жирный
font-weight: normal | bold | 100..900. Подбор: браузер синтезирует промежуточные «жирности» при недоступности файла. Скринридер не «утолщает» чтение — только текст. 700 обычно = bold. 400 = normal. Заголовки bold «поумолчанию». Сила жирности — визуальный крик: используйте дозированно. Сверхжирный шрифт «кричит», но читать тяжело. Для «важного слова» — strong в HTML, а CSS уже сделает bold сам. Проверьте в DevTools, какой файл реально грузится. Шрифтовые дорожки — целая наука придёт позже.
Трансформация регистра: text-transform uppercase
text-transform: uppercase | lowercase | capitalize — «переодеть» регистр без изменения HTML. Кнопки и бейджи в верхнем регистре — да, и текст в HTML остаётся «приличным». Скринридер прочитает именно HTML-текст, а не преображённый — не прячьте смысловую разницу в регистре. Акронимы в/заглавных: используйте в коде уже заглавные! Правило: не полагайтесь на визуальное преображение для сокращений. Простое правило: в CSS — красиво, в HTML — точно. «НАТРИ» в разметке — крик; text-transform — аккуратный журнальный заголовок. Выбирайте.
Псевдоэлементы: ::before и ::after
::before / ::after — «воображаемые дети» элемента, рисуются CSS'ом. content: "" обязателен — иначе не появится. Для иконок-маркеров, разделителей, декоративных деталей. Не несут смысла — они украшение. Скринридер их не читает: не «прячьте» важный текст внутрь. Пример: a::before { content: "→ " } — стрелка перед ссылкой. Чистый HTML остаётся пустым. Помните: псевдоэлемент живёт внутри проистекающего бокса: он «дитя» родителя. Декор средствами CSS — культура вёрстки, а не «мусор» в разметке. Красиво и чисто.
Наследование width у блочных: авто в деталях
Блочные «по умолчанию» width:auto — «заполняет» родителя целиком. Ещё про «край»: margin не «входит» в width. box-sizing «меняет» «вселенную»: content-box (классика) vs border-box (современный стандарт). * { box-sizing: border-box } — «спокойный» подход: ширина включает padding и border — проще математика. Парадокс: без border-box «100% + padding» = перенос строки. Включите border-box «вручную». Майкл Хартл «советует»: универсальный селектор для reset. Это «мелочь», экономящая часы. Привыкайте к «доброй» ширине.
Отсутствие переноса: white-space теперь-и-навсегда
white-space:nowrap «запрещает» перенос: длинные надписи кнопок, чипы тегов, логотипы. Пара «с» text-overflow:ellipsis «обрезает» многоточием. Двойное оружие: nowrap + overflow:hidden + ellipsis — «кнопка без разрыва». Почитайте: white-space наследуется. pre-wrap «сохраняет» пробелы. pre-line «склеивает» лишние пробелы, но «переносит» сами строки. Дисциплина строк: перенос «решает» читабельность. Не «резать» слова в «середине» вне словарей. Тонкая грань: nowrap — благодать узких кнопок; но текст не «для» прокрутки горизонтальной. Мера в каждом свойстве.
Палитра из документа: currentColor скрытая магия
currentColor — «текущий цвет текста»: рамки, тени, фоны «могут» от него «зависеть». Изменяем color у родителя — «всё» окрашивается разом. Иконки SVG «наследуют» currentColor — гениально для кнопок. border-color:currentColor — «само-синхронизация». Иногда проще, чем дублировать один и тот же #hex в четырёх местах. Утроить надежность: одно определение цвета. Применяйте в h2::before и маркерах. Эстетика данных в коде: «меньше повторов — больше смысла». Попробуйте декоративные ::before с currentColor — цвет «плывёт» с текстом.
Многозадачность background: shorthand и слои
background — «общая» декларация: color + image + position + repeat. Порядок «в» shorthand «не» строгий, но «согласованный» помогает. Несколько фонов: запятые через слои: url(a), url(b). Первый слой «сверху». Понимание «цвет-под-картинкой» — запас спокойствия при загрузке: пока картинка «не» пришла, цвет уже есть. Советы: убедитесь в repeat/no-repeat: фон при «тающем» контейнере «не» «съест» память. Практикуйте shorthand «после» длинных форм — начнёте писать быстро и компактно. Слои — как стопка бумаги: верх «видно», нижний — «фон».
Свет из коробки: box-shadow в нюансах
box-shadow: h-offset v-offset blur spread color; — тень как «отстой». Четыре числа: растирание, смещение, размытие, радиус; «внутренняя» inset «утапливает». Множественные тени — через запятую: реалистичность многослойной «глубины». Привычка: blur маленький = резко, большой = мягко. Тень «не» для «богов»; аккуратность — дозированность. Не «делайте» картонную коробку из каждого div. Слой эффекта: соответствие источнику света сверху-слева. box-shadow у hover — «подъём» карточки без JS: зазор ощутим. Техника CSS: тень — «скульптор» плоскостей.
Одно слово — свой оттенок: color перевод в палитру
Ключевые слова: red, blue, green, transparent (текущий фон), currentColor в наследовании. Никогда не «полагайтесь» только на имена-слова для целей между днями. Привычка переводить слова в HEX — точность. FF0000 = красный, 00FF00 — зелёный, 0000FF — синий. Микс с прозрачностью: rgba с alpha. Выбрать «тон» — это связь с дизайном. Храните палитру в CSS-переменных (var(--primary)). Это фундамент будущих тем: аккуратность в каждом пикселе. Словарь «слов-цветов» не велик, но точность «выбирает» тон. Точность = уважение к конечному виду.
Обычный фон: изучить цвет через линейный градиент
linear-gradient — «плавный» переход цвета одного в другой (или через несколько стопов). Направление: to right, 45deg, to bottom. Стопы: цвет + позиция: red 0%, blue 100%. Повторение: repeating-linear-gradient для полосатого паттерна. Градиент — это фоновое изображение (background-image), не цвет. Прозрачность стопов: rgba. Эффекты глубины: свет сверху. Помните: градиент не «для» всего текста — читаемость прежде. Слои фона можно комбинировать. Полоски, «закаты», «стекла» — дело вкуса. «Смелее» экспериментируйте на декоративных плашках.
Заголовок сквозь градиент: маскировка текста
background-clip:text + color:transparent — «заливка» текста градиентом: роскошный заголовок без картинки. Обязателен -webkit- префикс для WebKit браузеров. Осторожно: прозрачный текст «без» фолбэка становится невидимым. Проверяйте поддержку: text-fill-color: transparent. Комбинация декоративна: подходит для броских hero-заголовков (1-2 слова). Не «злоупотребляйте» — читабельность первична. Яркое слово «Акция» градиентом — эффектно. Но доступность: убедитесь, что фоновый градиент контрастен тексту, если он остался видимым без клипа. Практика: одна строка-заголовок с золотым переливом.
Первый взгляд на каскад: перекрытие по порядку
Каскад — «кто последний, тот и главный» при равной специфичности. Два правила на цвет p — выигрывает нижнее. Порядок в файле решает. Поэтому «позже» подключённый CSS «перекрывает» ранний. HTML порядок не «говорит»: стиль из head и из файла — последний линк побеждает. Не «устраивайте» битвы между файлами — система подключения «предсказуема». Изучите: специфичность считает id>class>tag. «Взвешивайте» селекторы. Дисциплина каскада — так вы контролируете «кто» скажет последнее слово. Иначе двадцать правил спорят за абзац — а браузер один.
Тонкая настройка: свойство font-kerning
font-kerning: auto | normal | none — «кернинг»: уточнение расстояния между парами букв (AV, To). auto — браузер «решает» по данным шрифта. Подключённые веб-шрифты «несут» кернинговые пары. Экономная типографика: кернинг «виден» в крупных заголовках. Субтитры — не «развалить» пары. Неопытные руки «отключают» кернинг целиком — теряя профессиональный вид. css-tricks советует: с крупными размерами шрифта включайте auto — на 64px чудесно. Проверьте контраст пар: «То», «Wa» в русском — «Tо»? Русский редко страдает. Кернинг — укрепление типографического «моста» меж букв.
Выделенные кнопки наведения: теплее канваса
Состояния кнопки: normal / hover / active / focus-visible. «Теплее» при наведении: hover меняет фон на пару процентов ярче. active «нажимает вниз»: translateY(1px). focus-visible: outline. Каждое состояние «отвечает» на вопрос пользователя: «я смотрю», «я жму», «я дошёл». Не полагайтесь на один hover — на сенсоре его нет. Комбинация состояний «прошивает» кнопку живым откликом. UX-привычка: изменять background и border одновременно. Тест-лист: наведение → нажатие → фокус с клавиатуры. «Тёплая» кнопка «подстраивается» под действие. Оформление состояний — культура доступности.
Второе правило восприятия: ничего без margin
margin — «пустое пространство» снаружи границы; задаёт расстояние между соседями. Начало понимания сетки: margin-bottom у параграфов — «воздух» текстового потока. Углы: margin «не» «склеивает» соседние (схлопывание вертикальных margin — классика). Свойство «в норме»: px, em, %, auto. Вертикальное схлопывание: больший из двух margin «побеждает» между блоками. Не «дублируйте» margin: у p уже есть отступ по умолчанию. Сетка дышит не «липкими» пикселями, а «ритмом» воздухов. Посмотрите: расстояние «между» карточками = margin; «внутри» карточки = padding. Asymmetria полезна, когда осмысленна. Осознанные отступы — «чистая» геометрия.
Визуальные уровни: свойство z-index и условия
z-index управляет «глубиной» наложения в трёх осях (z). Работает только на позиционированных элементах (position:relative|absolute|fixed|sticky). Число целое: больше — выше. Слои: модалки (999), тултипы, шапка. «Не» «накручивайте» миллионные стеки «на глазо» — применяйте 10, 100, 1000 как «этажи». auto возвращает в поток. Ловушка: свойство «не» видит элемент без position. z-index дробный? Нет — целые. Стек-контекст: элементы формируют локальный порядок в родителях. Понимание «глубины» — половина борьбы с наложениями. Модалка должна быть «выше» шапки: 1000 > 100. Тень и «перекрытие» — один каскад.
Замысел справа: практика с псевдоклассом :root и переменными
Объявите в :root переменные: main-color, accent, radius, gap. Используйте var(--main-color) в правилах. Так вы — «хозяин палитры», а не «пленник» чисел. Сменить оттенок = одна строка. Тема тёмная = переопределение переменных под медиа-запрос. Сделайте карточку с переменными. Сверьте Computed. Переменные — «мембрана» между настроением и кодом. Элегантность закладывается в объявлении. Сегодня заложите «скелет экономии».
Уха за каскадом: откуда браузер берёт базовый шрифт
Шрифт по умолчанию — «из» браузера, но user-agent стили «могут» задать свой. Не «полагайтесь»: явно задайте font-family на body. Без этого — «шрифт планет» странный. Наследование: шрифт «капает» вниз от body. Заставьте Google Fonts подключить — потом «займёт» место. Системы: 'Segoe UI', Roboto, Arial, sans-serif. «Перевод строки» скринридер-семантика — не шрифт. Побеждает явность + наследование. Красивый базовый шрифт — уважение к тексту. Начинайте с него всегда.
Пара пар: text-shadow — тень без графика
text-shadow: x y blur color; — тень текста. Слегка поднимает заголовок над фоном. НЕ «злоупотребляйте»: длинный текст с тенью — грязно. Несколько теней через запятую — «мягкое свечение». Не цветной неон «на» всем. Tёмный текст + светлая тень = «выбор» из фона. для легенд и героев. Профессиональный минимализм. Никогда не «прячьте» текст тенью ради «красоты без смысла». Доступность: контраст сохраняем. Type-trick: тонкая тень крупного заголовка — эффект «эмбоссинг».
Поток против потока: все про display: table-cell
display:table / table-cell — «возрождение» табличной раскладки без тегов таблицы. Устарело в эпоху flex/grid, но встречается. Для центрирования по вертикали: display:table-cell; vertical-align:middle на родителе. Полезная аварийная техника в легаси. Не «бегите» к ним для новых макетов. Знать = понимать легенду вёрстки. Совместимость: работает везде, живучая. Если видите table-cell в старом коде — не «ругайтесь», «расшифруйте». Мастера читают историю стилей. Рефакторинг — на flex/grid при случае.
Пустая классика: псевдоклассы для списка производства
Псевдоклассы «места»: :first-child, :last-child (по умолчанию также), :nth-child(2), :nth-child(odd/even), :nth-last-child. Списки и сетки «оживают» зеброй, пропусками, акцентами. :nth-of-type — «среди» тегов. Ещё: :only-child. Практика: «выделите» первый и последний пункт меню. Зебра таблицы без классов вёрстки. Семантика уровня CSS. Не «размазывайте» их в JS, когда CSS может сам. Знания «позиций» — точность к первому/последнему. Звучит как магия — это просто индексы.
Устойчивые списки: маркер ваш друг, а не враг
У списков маркеры: диск, круг, квадрат; list-style-type: none для нав-меню; картинка-маркер: list-style-image. «Не геометрия»: маркер — знак «пункта». Отступы: padding-left у ul. Не «пропадайте» маркеры при вложенности — переопределения. Скринридеры числа списков читают. Право выбора: произвольные маркеры через псевдоэлемент. Список без маркера — «тайная» структура, читается семантически. Управляйте «списком-знаком», давая пользователю «порядок» в глазах. Не температура спайка: точка — целая система.
Дирижёры строк: личная и вышки list-styling
CSS «умеет» списки: list-style — сокращение для type/position/image. list-style-position: inside | outside. Текст второго уровня переносится «к» маркеру или рядом. По умолчанию outside. Внутри (inside) — маркер в тексте, отступы плотные. Не путать доступ. Позиция маркера — мелочь типографики. Большой список с inside: компактно. Списки в меню — часто outside + padding. Универсальность через «сочетание». Опыт: выберите одну «стоечку», держитесь её. «Ритм» списка — повторяющаяся река текста. Аккуратный list-style — признак классики.
Хвосты маленьких выборов: text-decoration поля и строки
text-decoration — underline/overline/line-through + стиль/цвет. Для ссылок по умолчанию. Многоцветный декор — отдельные цветы. text-decoration-thickness — толщина. text-underline-offset — «отодвинуть» линию от глифов. Ссылки без underline при наличии hover-underline — тренд. Но доступность: не «снимайте» полностью без альтернативы. Подчёркивание — машинная семантика «клика». Украшение кода не кодит строки. Цвет декора может наследоваться currentcolor. Дизайнерам: «игра» с толщиной — типографический флер. Аккуратность в мельчайших линиях.
Списки в CSS Grid: карточки-строки рядами
«Ряды» — display:grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)). Список карточек станет «текучей сеткой». Ломает «строку» и строит «полки витрины». «Зазоры» — gap: 1rem. li — «ячейка»; стилизуем как «товар». Медиа-запросы почти не нужны — сетка сама «подстраивается». «Вариации»: auto-fit для пустого последнего ряда. Низы карточек — align-stretch. У каждой «ячейки» — та же «полка». Это «выгодная» алгебра раскладок. Списки из формул — «полуфабрикат» вёрстки. Продолжайте: каждый li дышит «своей» псевдоячейкой.
Форма моя крепость: стилизация интерактивных полей
Практика стилизации форм: input/select/textarea — свои состояния: фон, рамка, padding, font. Фокус: рамка акцентная. placeholder — серый. «Ошибка» — :invalid/псевдоклассы. Не «желтите» всё — теплее по смыслу. Какое поле «важно» — у него сильнее рамка. Атрибут visuals «не в» HTML — CSS. Пробелы форм — вертикальный ритм. Повторение «паттерна форм» — похвала вёрстке. Читаемость и комфорт ввода — «аромат» форм. Label «в» CSS: дизайн пары. Форма без «скучного» серого — «лицо» взаимодействия.
Зачем эмодзи и роли: эмоции в callout-блоках
Эмодзи «мысль — ярлык» для типа блока: 💡 — совет, ⚠️ — предвтрег, ❗ — результат. Не «разбрасывайте» их «в» каждом абзаце — «в» заголовках icon-блока. Мраморный настрой: эмодзи уместны и «вниманием» окрашены. Технические: .callout.hint > span. emotion — не «содержимое», а «мотив». Умеренность: 1 эмодзи на заметку. Emoji настраивают счётчики (ради кода), но разметка остаётся текстом. В скринридере: 💡 читается «лампочка» «иногда» — «не» полагайтесь «на» него. Практика: добавьте «ярлычки-эмодзи» всем callout-блокам текущего урока. Стиль — «голос» вкладки.
Термин потребности: aria-label для групп переключателей
Переключатели (радио) в группе «нуждаются» в имени. fieldset + legend — «пароль». Но «icon-only»-группа (кнопки-режимы) — role="group" + aria-label="Режим отображения". label на каждый input+radio сам «объясняет» значение. Навигация стрелками — JS. aria-label у fieldset? — legend это уже «имя». Не «перегружайте» скринридер «галочками». Тест: прочитайте группу на слух. Атрибуты «и» роли — аллергия на вслепую подачу. Доступность форм — точность семантики. Смыслы не «запираются» в одних label. Группируйте «нейминг» — как теги в архиве. Профессионал «слышит» форму.
Кнопки-чипы: инлайн компактные фильтры
Чипы — «маленькие» фильтры-кнопки: inline-flex + padding + round radius. Активный — «фон заполнен», неактивный — «контур». Удаляемый крестик — svg + aria-label «Удалить фильтр». Скопить: группа role="group" aria-label="Фильтры". Каталоги сложные. Клавиатура: стрелки «перемещают» между чипами (JS). «Не» делайте «ради разнообразия» — первыми «выскочат» скринридеры. Маленькая деталь — большая практика ток-ток. Состояния: selected/disabled. Чипы «живут» в формах и поиске. Соберите панель фильтров курса: Тема/Уровень/Формат. Проверьте фокус. «И» стиль.
Псевдокласс роли: :has сдерживает тень
:has() — «родитель, у которого есть…»: .card:has(img) — «карточка с картинкой». Революционный «взгляд» вверх по DOM. Стилизация карточки по содержимому — без JS-переключения классов. .form:has(input:focus) — «оживает» подчёркивание у всей группы. Доступность: скринридер «игнорирует». Валидность: поддержка хорошая (2023+). Применение: выделить «товар с доставкою», статью с видео. Сила: CSS теперь «сморит на» детей и «разговаривает» стилем. Не «слепить» :has везде — производительность редких мест. Небольшой аккуратный :has() = вау-футер. Элегантность каскада будущего в форме условия.
Баг или фича: включите логический поток grid
break-inside: avoid — «древняя» печать/колонки: карточка не разрывается «между» страницами/колонками. Применение: div в columns:2. break-before/after — «очередь», страница/столбец. print — тема печати. Веб: «разные» кросс-браузерные вариации свойства (page-break-inside старый). Не «пихайте» на каждый элемент. Пример: блок «не разрывается» — столбец скрипит аккуратностью. В печатной вёрстке — «честный» разрыв. Привыкайте читать print preview. Этот «разрыв» вёрстки — «технический» экзамен. В зависимости средства: печать по умолчанию рвёт «как придётся» — теперь вы решаете.
Tab-индекс и форм-фокус: дисциплина вхождения
Порядок фокуса в формах — DOM-порядок совпадает с Tab-порядком. Не «изменяйте» tabindex положительный без нужды: значение 1,2,3 «переопределяет» универсальный порядок. Валидная практика: в полях «естественно»: имя → email → телефон → кнопка. Скринридер «ходит» так же. «Прыгающий» фокус — наказание. «Отлток»: одна форма — один маршрут. autofocus — «крайне» редко (помощь поисковой строки). При «новая» вкладка — фокус на «контенте». Проверьте пальцем по клавиатуре: почта → телефон. Дисциплина фокуса — «текст» без мыши. Формы — «ворота», фокус — «ключ».
Практика: анкета с согласием и aria-лайбл
Соберите анкету: имя (text), возраст (number), email, город (select), любимая тема (radio 3), согласие (checkbox), submit. Все label связаны. В поле имя — required. checkbox — «согласен с обработкой» + aria-required="true". Разделите fieldset/legend. Валидация браузером «живёт» сама. Проверки: Tab-порядок, фокус-виден, скринридер читает поле и подсказку. Практика — демо «общественная форма». Сохраните. Завтра добавите стили. «Анкета» похожа на «настоящую». Семантика держит. Экзамен: дайте другу пройти форму вслепую.
Шрифт-пара для форм: удобство чтения чисел ввода
Числа в формах: monospace — «ровные» ширины для кода/промокодов? Для «обычных» цифр — tabular-numbers: font-feature-settings "tnum" или font-variant-numeric: tabular-nums. Промокоды, телефоны, счета — «пересчёты» не «съезжают». monospace для «кода» в textarea — помощь выравнивания. «Понятные» числа = «спокойный» ввод по колонке. Не «зажимайте» прописные. Домашняя практика: таблица цен с tnum. Цифры в колонке «стоят» чинно. Дизайнерский акт: данные читаются, а не «прыгают». Единицы шрифта и ритма форм сходятся в вашу пользу: просто красиво и профессионально. Числовой ритм.»
Показательный ряд: инлайн формы в одной строке
Инлайн-форма: label+input+button «в» одну «строку» — поиск, подписка на рассылку. Вертикальные «друзья» через flex: label «не» «рвёт» строку; выравнивание по центру. «Глубина»: без flex — строка «текучая», с gap — «ровная». placeholder пример. Кнопка «не» «уезжает». Скринридеры «прочитают» каждое поле. Не «сжимайте» в одну «липучку» — оставьте «дыхание» gap: 8px. Форма-«строчка» — классика подвалов и шапок. Проверьте Tab: фокус движется в ряд. Мобильная: кнопка «падает» на новую строку (или вниз). Инлайновость — «скорость» и «место». Удобно и честно. Красиво, когда «всё в ряд» и ничего не «толкается». Практикуйте в подвале: «Подпишитесь на новости» + ввод + стрелка. Малая форма — большая привычка.
Зрительный портрет: aria-label на чипе-иконке
Иконка-чип без текста: <button aria-label="Поделиться">🔗</button>. Скринридер «прочтёт» метку вместо эмодзи. В приложении, где иконки «говорят» сами — aria-label «обязателен». Если рядом есть видимый текст — label лишний. «Поддавая» сам себе в тестах: «как бы я назвал это другу по телефону?» — это и есть label. Доступность не «красит» чип, а «называет» его. Клик — действие; имя — понятие. Отдельный класс .icon-btn + aria. Учите: каждый «немой» контрол «получает» имя. Скринридеры это «любят». Инклюзия начинается с имени. Не «стесняйтесь» повторного слова — точность важнее новизны. Помогайте себе: таблица иконок + меток в проекте.
Каскадные братья: шрифты и специфичность семей
Семейства шрифтов «связаны» со специфичностью: .title vs h2 — кто «конкретнее»? специфичность не «про» шрифты, но форма каскада «та же». Правило с классом «бьёт» правило с тегом для одного элемента. font-family «наследуется», но селектор «решает», где применится. Устанавливайте базовые шрифты на body (0-0-1), а надписи-детали — классом. Если «путаница» — считайте весы. Шрифт «плывёт» по наследованию «в» нутро «без» классов. Снова: специфичность — «арбитр», наследование — «река». Держите их различие — и «прощайте» CSS-драмы. Заголовок «крупнее», абзац «мельче» — но семья одна. Единый tone of voice: один шрифт = слово = ритм. Не «жонглируйте» десятком семей «на» одной странице — каша в глазах и ухе. Дисциплина семьи — дисциплина смысла.
Упражнение с весом: три вкладки-селектора и вес 1-1-0
Соберите три «вкладки» в tab-группе: .tabs > .tab.active — специфичность 0-2-0 против .tab (0-1-0). Правило активной «побеждает» при «равно» источнике. Псевдокласс :hover на .tab — «добавляет» +10. Итого hover-active 0-3-0. «Считайте»: чем «глубже» цепочка, тем «весом». Упрощайте селекторы, если начали «перевешивать». Вкладки с иконками — кнопка+место. Переключение JS позже; сейчас проверьте, что СSS готов. Смысл: вес — «договор», который вы «знаете» наизусть. Если .tabs .tab.active не «перебил» кнопку — смотрите, где id или inline. Уверенный стилист «говорит» браузеру весами, а не криком. Дисциплина весов = меньше !important «и» меньше сюрпризов. Три вкладки «покажут» вашу математику каскада на деле. Практика окупается за секунды.
Визуальный «менеджер»: псевдокласс :root для палитры
:root — «корень документа». В нем — CSS-переменные (custom properties). --color-primary: #e44; var(--color-primary). Палитра «живёт» в одном месте. Тема-переключение: меняем переменные. «Не» дублируйте цвета по файлам. --base-gap: 1rem — сетки. Улучшение читаемости: переменные-имена «говорят», каким цветом. Скринридеры «не» читают переменные — это CSS — им просто «всё равно». Дисциплина: одна палитра → меньше «легенды» в голове. При сочетании с :has — «живёт» тема. :root — «пульт» всех стилей. Поменяли --bg → весь сайт «переоделся». Практикуйте: начните с 6 переменных. Это первая «пружина» дизайн-системы в вашем коде. Вскоре темы будут «плодиться» парами строк. Палитра в :root — «конституция» вёрстки.
Псевдокласс :focus-visible вместо слепого :focus
:focus-visible — «фокус только для клавиатуры» (обычно). :focus — «фокус вообще» (мышь тоже). Меньше «радужных» рамок при клике — сохраняем эстетику. Клавиатура — очевидные контуры. браузер сам «выключает» visible при клике в большинстве. Стандарт современности: outline на :focus-visible. Скринридеры «работают» вместе. Не выключайте outline полностью — «глухие» клавиатуры. a:focus-visible, button:focus-visible. Правило: «видимый фокус = карта навигации». Убрали — украли путь. Совместимость: все современные браузеры. В DevTools: эмулируйте фокус-визибл. Практика: выберите свой outline 2px dashed. Инклюзивный «свет» по маршруту: клавиша за клавишей. Репетиция: пройдите страницу одним Tab. Дисциплина фокуса — доступность в «потоке». Красивый и честный контур — признак мастера.
Вложенные детали: как читать каскад наследника
Наследование «капает» вниз по дереву: color, font-family, line-height, letter-spacing наследуются. Не наследуются: background, border, margin, padding, width. Применяется «согласие»: родитель задал — ребёнок «принял». Переопределяй намеренно. :root наследует в html → body → * … «Глубина» — удобство: задали line-height на body — все абзацы «дышат». Если «неожиданно» у наследуемого свойства не тот вид — проверьте: не «сброшен» ли случайно. Наследование — «смысловая река» документа. Понимание «кто кому» — половина CSS. Используйте наследование для «ритма», не «считайте» его магией. Частая ошибка: думать, что margin наследуется. Каскад и наследование — «два разных русла» одного потока. Знайте разницу — работайте спокойно. Тишина в коде — понятность.
Осознанный скролл: experiment с position: sticky внутри
position: sticky — «прилипает» при прокрутке «до» границы родителя. Шапка секции, подзаголовок списка, кнопка «наверх». Свойство: top: 0; как только элемент дойдёт до верха — «замрёт». Отличие от fixed: sticky «живёт» в потоке, потом «прилипает». Родитель должен быть «выше» по высоте, чем элемент — иначе не «застрянет». Используйте для «закреплённых» заголовков колонок в длинных списках. Не «залипайте» всё подряд: nav фиксирован? — обдумайте. Скринридер «не слышит» sticky (это визуально). Тест: прокрутите длинную статью — заголовок «остаётся». Sticky — «клей», но «дозированный». Доступность прокрутки: «не» воруйте всё пространство. Комфорт чтения — приоритет. Редко, но «метко». Проверьте на мобильном: инерция скролла.
Типографский ритм: единицы и «каскадный» шаг
Ритм типографики: отступы кратны базовой строке. line-height 1.5 × font-size = «единичная» линия. margin-bottom: 1.5rem «совпадает» с межстрочной. rem для шрифтов: адаптивно; em для локальных. Каскад наследует шаг. Заголовок 1.2 line-height; абзац 1.5. Базовая линия «строит» колонку. Та же музыка в списках и таблицах. Вертикальный ритм — читабельность и «спокойствие». Минимум: 1-2 базовые единицы для всех отступов. «Четыре» базовых шага? — Богато. Скринридеры «не» «слышат» ритм — но мозг берёт «верх». Типографика — «невидимый дирижёр». Единицы: ритм; rem — базовый дирижёр. Практика: переберите страницу с line-height:1.6 → 1.8 — почувствуйте темп. «Размер» букв и «междустрочье» — дыхание текста. Красиво и доступно. Мастерство — в «паузах».
Польза инспектора: Computed для каскадных секретов
DevTools → Computed — «итог» всех каскадных сил. Видно конкретное значение (вычисленное). Ссылка «на» правило — переход. Цвета, размеры, вес. «Зачёркнутое» — проигравшие. Листайте «вглубь» — как слои. Инспектор «объясняет», почему «не» применилось: специфичность, источник, порядок. Кнопка «Computed» - ваш «рентген» каскада. Не «гадайте»: смотрите числа. Практика: найдите конфликтную строку и «отмените» её — сразу видно. Учитесь читать «борьбу правил». DevTools — бесплатный профессор. Селектор «наведением» подсветит. Инспекция — ежедневный ритуал мастера. Не запугивайтесь «кишечником» вкладок: только Styles и Computed пока. Остальное — по мере. Каждое «почему?» теперь — клик, а не поиск. Быстрее и честнее. Диагностика каскада — ваша новая суперсила. Практикуйте чаще.
Свойство writing-mode и вертикальный текст бренда
writing-mode: vertical-rl — текст «снизу вверх» (как японские). Для «бренда», бирок, обложек. Горизонтальный-по умолчанию; «туда-сюда». Ось строк меняется: width/height «меняются местами». Скринридер читает по строкам текста (вертикально создаёт «колонку»). letter-spacing эффект. «Не» делайте весь сайт вертикальным — экстремизм. Кейс: бейдж «Назад в топ», витрина. Многие браузеры — поддержка хорошая. Для «режима письма» и языков — важно. Text-orientation: upright/mixed — поворот букв. Бренд-вертикаль — «тихая» изюминка макета. Проверяйте на разных шрифтах: некоторым не хватает глифов? «Вертикально»: осторожно с кириллицей — буквы не «ложатся» на бок. Комбинируйте смело, но деликатно. Дисциплина письма = уважение к языку. Практикуйте на брошюре-флаере. Vertical — «трюк-вишенка».
Обвязка деталей: аттрибут dir для встроенного RTL
<bdi> — «изолированный» кусок текста, направление которого может «выбиться»: имена, номера. Скринридер и браузер «не путаются». Атрибут dir="rtl" на контейнере: для арабского/иврита. Встроенные числа в русском: «не» переворачиваются. <bdo dir="rtl"> — принудительный разворот (редкость). При смешении языков — валидность и чтение. Не «прячьте» направление в CSS. Семантика направления — атрибут, не стиль. Тестируйте: текст с арабским именем внутри русской строки. Unicode bidi — сложно; тег bdi «снимает» боль. Проверка поддержки: все современные браузеры. Скринридеры «слышат» правильный порядок. Приятный бонус: «nofollow» направление остаётся. Для форм с именами — bdi вокруг значений. Меньше «сюрпризов» в UX разных культур. Инклюзивный и понятный. Уважайте двунаправленность мира — размечайте аккуратно.
Домашнее задание: мини-хранилище переменных темы
Соберите «настройщик темы» на CSS-переменных: :root с --bg, --text, --accent, --radius, --shadow. Три варианта пресета через классы на body: .theme-dark, .theme-light, .theme-solar. Переключение JS — позже; сейчас просто классы. Проверьте: смена класса на html меняет фон/цвет. Значение «каскада»: переменные переопределяются «селектором», а не «местом». card «использует» var() — «реагирует» на тему. Практическое зерно: дизайн-токены в переменных — «фундамент» системы. Сделайте кнопку «Тема» (без JS, просто демо). Скринридер «не видит» тем — это визуальное. Проверка: контраст текста в каждом пресете. Адаптив: одна переменная — «одна» замена. Выполнено — значит, вы поняли суть тем и роли :root. Чистый CSS — чистая архитектура. Тренируйте грамотно.
Инспектор и счётчики: считать поля жизни списка
Сила списков в таблицах счёта: start, value, reversed. <ol reversed start="10"> — обратный отсчёт. value на li — «переопределить» номер: список «шагов с пропусками». CSS counters — через ::marker? номера — часть контента, а не CSS. «Значение» — данные: шаги, главы, позиции. Дебаг в DevTools покажет «вычисленный» номер. Скринридеры считают элементы списка. Не «полагайтесь» на видимые номера — они из order HTML. start="5" для продолжения главы. Для рейтингов reversed + value. Списки выглядят «по-настоящему» живые: «пропуски» объясняют. Дисциплина: order-атрибуты — часть данных. Убедитесь: валидатор «не ругается». Практикуйте список-конспект с begin 1,2,3… «живая» нумерация без JS. Счёт — «скелет» повторяющегося. Узрите: нумерация «несёт» порядок, а порядок — обещание. Значении для разных языков — числа. «Считайте» уверенно.
Тихий показ: свойство opacity и игра со слоями
opacity — «прозрачность» элемента целиком: 0 скрывает, 1 — непрозрачный. Влияет на весь элемент + потомков (пигмент). Не путать с visibility:hidden (место остаётся) и display:none (выпадает из потока). content в opacity? — «весь блок тускнеет». Переходы opacity — «плавное» исчезновение: популярно в UI. Про то, что «не» наследуется. Применение: водяные знаки, лёгкие оверлеи. Скринридеры: opacity:0 элемент «всё ещё» в дереве (читается!) если не display:none. «Трюк»: opacity — «дешёвая» анимация (GPU-friendly). Чередование в тостах. Аккуратно: 0.5 на текст — снижает читаемость. Та же «муть» для фоновых подложек — отлично. Плавность: transition: opacity .3s. Fade-эффекты «живут» здесь. Вершина простых анимаций — opacity + scale. Тихая палитра — сила. Практикуйте on-hover: 0.7 → 1. Деликатно.
Зачем нужен overflow: контейнер шире разговора
overflow — «как себя вести», когда контента больше, чем бокс: visible (вылезает), hidden (обрезает), scroll (полосы), auto (полосы при необходимости). overflow-x и overflow-y отдельно. Скрытие «побочных» детей через hidden — классика слайдера. В сочетании: белое пространство — «не» утечка. Проверяйте: у caret-hidden может «выпасть» тень. Скринридеры: overflow:hidden не «убирает» из DOM — контент читается (для форм-карусель это важно?). Делайте любые «тоннели» аккуратно: не живите «в» прокутке внутри прокрутки. «Орлиный» глаз: если скролл-полоса не нужна — auto. Горизонтальный скролл — признак тесноты: пересмотрите сетку. Практика: обрезайте «длинную» строку многоточием: overflow:hidden + text-overflow:ellipsis + nowrap. Это «не» калечит, а «причёсывает». Overflow — «ножницы» бокса: видите, чего не хотите показывать. Управляйте потоком с достоинством.
Блочные родные: не только p — универсальная боль childhood
Блочные элементы: div, p, h1-h6, ul/ol, li, section, article, header, footer, main, blockquote, figure, form. Все «прижимают» соседей вниз. Каждый — «новая строка». Ширина — вся доступная (блок). height — по контенту. «Правило-детство»: блочность — не «злодей», это «порядок по умолчанию». Меняет display — CSS. Не «выпрямляй» руками — поток «сам». Строку вытащил строчно-блочным? Подумай. Смысловая иерархия часто идёт «блоками». Список из article — блоки. Цитата — блок. Форма — блок. «Не» «стыдись» блочности — на ней стоит весь веб. Блочная модель — «стержень» CSS. Практикуйте мысленно: «это строка или блок?» — отвечайте разметкой. Даже если CSS «позволяет» иначе — поток «не устаёт». Управляйте правильно. Диаграмма потока — лучший наставник. Спокойный поток — спокойная вёрстка. Дисциплина бокса — ежедневная гимнастика ящиков.
Строчные в потоке: когда text-align мать порядка
Строчные элементы (span, a, em, strong, img inline) — «текут» по строке. text-align: left|right|center|justify — «выравнивание» строковых боксов. Применимо к блочному контейнеру. Left по умолчанию. Center — заголовки. Justify — «растягивает» между полями — может дать «реки». Строчные «не» принимают width/height, margin по вертикали «не работает». Для «центровки» строчной картинки внутри блока — text-align:center. Скринридеры: выравнивание CSS «не» слышно — только смысл. «Приёмы»: почините «дышащий» текст через text-align. Многострочные строки внутри inline-block. Горизонтальный ритм: выравнивание задаёт «берег» колонки. Длинные цитаты — центр? — только заголовок. Соблюдайте читаемость: justify на узких колонках — риск «дыр». text-align — «дирижёр строкового оркестра». Понимание «строк/блоков» — фундамент. Играйте: «центр» против «левого» — почувствуйте. Мера — ваш шаг.
Формы-братья: инпут против textarea против select
Однострочное — input; многострочное — textarea; выбор из списка — select/option. textarea rows/cols + resize: vertical. select collapsed + optgroup. input «для» коротких значений; textarea — «пространные». Семантика: каждая роль «своя». Не «злоупотребляйте» textarea для «пароля» (это input type=password). Скринридер: select «через» стрелки «открывается». maxlength автоматически — у textarea «есть». placeholder — пример. label «связан». Пара: <textarea name="comment" rows="4">. Форма-«текст» отличается от формы-«выбора» — читается. Валидация браузером минимальна; JS — глубже позже. «Гнусность» сценария: input для длинных абзацев — потеря «потолка». Проверяйте, что поля правдоподобны по типу. Многострочность — доступность для «развёрнутого» ответа. Дисциплина выбора поля — часть UX. Форма «моя» и «твоя» — правильно разложенная. Практикуйте педантично. Поток данных чист.
Гнездо колонок: table в центре fluid-страницы
Таблица «внутри» fluid-макета: width:100% + max-width; «дышит» вместе со страницей. table-layout:fixed — столбцы «по указанным» ширинам (предсказуемо). Быстрее рендер больших таблиц. Нужен явный width у col/th. Строгие «высоты»: white-space:nowrap может разорвать. Для больших данных — horizontal scroll-обёртка или sticky th. Адаптив таблицы: на мобильном превращается в «карточки» (display:block + data-label). Скринридер: карточка-таблица «читается» построчно? Используйте th scope=col. Контраст строк — уют глаз. Не «запихивайте» таблицу в карточку любой ценой: иногда это «список». Соотнесите: данные-рядки → таблица; данные-пары → dl. Пропорции: соотношение сторон таблицы — чувство. Практика: расписание в две колонки, затем мобильное «переложение». Гибкость данных — искусство выбора контейнера. Сетка + таблица — «сплав» правил. Держите фокус на смысле.
Псевдо-таблицы: grid против table для данных
Современный выбор: CSS Grid «рисует» сетку данных без table-тегов? Но скринридер «не» увидит «связь» строк/столбцов, как в настоящей таблице. Для «табличных» данных остаётся table (row/column семантика). Grid — для «макетных» ячеек (карточки, галереи). Не «меняйте» table на grid ради «красоты» — потеряете данные. Комбинируйте: table внутри grid-области? — да. А если «только» выглядит как таблица (прайс в 3 колонки) — честно решите: это «список» (ul) или «таблица» (данные). Вопрос «соотношения»: смысл данных диктует. Сетка — «город», таблица — «кадастр». Скринридеры читают таблицы заголовками. Обучение: превратите простую прайс-таблицу в grid? — и спросите себя о смысле. Частая ошибка: «весь» grid ради «незначительных» строк. Мудрость: выберите инструмент по данным, не по моде. Данные «любят» колонки родом «th». Уважение к структуре — инклюзия. Пишите семантику честно.
Интерактив без JS: details-аккордеон в списке тем
<details> — «раскрывающийся» блок без JavaScript: click — toggles. <summary> — «видимый» заголовок. Атрибут open — раскрыт. Скринридер «заявит» state (свёрнуто/развёрнуто). Соберите FAQ «нативные» — пятёрка вопросов. Внутри: div/p «содержимое». Хорошо: свёрнуто по умолчанию = компактно; «открытое» open — «вещь» важная. Не «вкладывайте» аккордеон «в» аккордеон глубоко. Group подробностей: details frame=добро. Доступность: summary — «button-like»: Enter/Space переключает. Стилизация: margin, border, ::marker. details/ul — аккуратная семантика. Держите логику «внутри» блока. Практика-мини: «Вопросы и ответы» урока без JS. «Новости»-спойлер. Немного усилий — «живой» паттерн. Поняв details — первая «интерактивность» без сценария. Проверьте в браузере и скринридером: state озвучен. Стили можно «нарастить» позже. Настоящий HTML «одушевляется» простотой.
Детали фокуса: tabindex без боли амулета
tabindex="0" — добавить элемент «в» порядок Tab-навигации (карточка, кастомный контрол). tabindex="-1" — «убрать» из Tab, но «оставить» фокус для JS (скрытые контейнеры). Положительные (1,2,5) — «ломают» естественный порядок: избегайте. «Одна» страница = «естественный» DOM-порядок + 0 для интерактива. Скринридер «не» «спотыкается» о tabindex. «Хирургия»: «свои» виджеты (вкладки, слайдеры) — управление стрелками (roving tabindex) — продвинутая практика. Не «вешай» tabindex на каждый текст. Если элемент «не» для клика — «не» делай фокусируемым. Проверьте: кликнули, потом Tab-порядок «чист». SKILL: DevTools → панель a11y «видит» порядок. Дисциплина фокуса — «невидимая» доступность. Практикуйте на навигации: focus visible никогда не «пропадает». Не «срезай» outline мышью — лечи селекторы. Фокус — «маршрут» для рук без мыши. Чистый tab-поток — профессионализм, ощутимый слепым и зрячим. Уважение к клавиатуре.
Куратор концовок: footer в разных гранях каскада
footer — «хвостовая» информация: копирайт, контакты, мини-навигация. Внутри article — «подвал статьи» (автор, лицензия). Полный деликатный «хвост». Каскад: стилизуйте footer один раз на странице. Скринридер читает footer «в конце». address в footer — «контакты владельца». Не «дублируй» навигацию главного меню в подвал; у подвала — «вторичные» ссылки. Семантика: footer «не» «прилипает» — он «в потоке». Для «липкого» — flex min-height. Слои: нём и «повторяющиеся» данные. Используйте <time> в copyright. Стилизуйте аккуратно: отсутствие «суеты» внизу «успокаивает» завершение страницы. Инклюзия: ссылки footer «доступны» из любой точки. Каскад: «последний» блок — «точка» затишья. Формы-мини (подписка) — тоже житель footer. «Пункт» ритма. Повторите: footer — «подпись» документа. Профессиональная, честная, не «кричащая». Дисциплина подвала — финал симфонии.
Псевдокласс :empty и аккуратные пустые блоки
:empty — «выборка» элементов без детей и текста. Отличный инструмент: скрыть пустую корзину («is-empty»). .cart:empty::after { content:"Пока пусто" } — «занятие» пустоты. Точность: пробел/комментарий в HTML — элемент «не пуст»!). «Одна» ловушка: <div> </div> — «не» пустой. Скринридер: :empty «не» слышит; контент-подсказку «сложите» в текст. CSS управляет «пустотой» визуально. Применение: пустые состояния в списках/таблицах. Не «добавляй» вручную классы is-empty руками JS — CSS сам. Каскад: :empty ниже «классов» — смотрите порядок. Гигиена: не оставляй «мёртвых» пустых div — удаляй. Если блок «пуст» по дизайну — подумай: нужно ли «семантически»? Можно просто опустить. CSS :empty — «умный нож». Меньше «манекенов» в дереве = чище чтение. Прайс «в» сети: пустая область «получает» фразу. Проверьте: загадка «один пробел ≠ пусто». Аромат аккуратности — в деталях. Доступный и минималистичный «вэб» любит пустоту, наполненную смыслом.
Овладеваем величиной: размеры и высоты шрифтовой гаммы
Сила шрифтовой шкалы: font-size 6-8 размеров (10→48px); modular scale (1.25) — «музыкальная» лестница. Заголовки 2,1.7,1.4 абзаца. line-height: заголовки «теснее» (1.1-1.3), текст «свободнее» (1.5-1.7). Эм/рем/пиксель: выбор. Отступ только по вертикали: margin-bottom 1.5em. Абзац «дышит». Не «добавляй» межбуквенный у огромного заголовка слишком. Weak: систематика размеров — читаемая иерархия. Скринридеры «не» слышат размер — зато мозг «иерархией» дирижирует. Количество чтание: 45-75 символов на строку. Ширина текста: measure. Проверьте: крупные абзацы «бегут» на всю ширину? Исправь. Сетка: базовая линия в 1.5 крат. Каскад наследует line-height. Практика: выберите модуль (1.25), расчертите страницу. Результат: типографика «поёт», цифры совпадают с чувством. Дисциплина шкалы — «молчаливый» профессионализм. Ритм-управление — приятное мастерство. Строки согласованы, глаза не устают. Оформите правило: «один модуль на сайт» — элегантность и порядок. Читаемость — король.
Повторение диаграммы: соседи-боксы это просто
Бокс-модель «на пальцах»: content — «содержимое», padding — «внутренний воздух», border — «граница», margin — «внешний воздух». Ширина: content + padding + border (без margin). alt text? — не про бокс. Разные display — «раскладка» боксов. Блочный занимает свою строку. Схлопывание margin — «вертикальные соседи». Для точной ширины: box-sizing:border-box — «помещение» padding в width. В DevTools виден «синий»=content, «зелёный»=padding, «жёлтый»=border, «оранжевый»=margin: смотрите. «Отладка»: квадратик-подсветка. Не «гадай» где «лишние» пиксели — считай. Каскад: размеры из правил. Скринридер: box-model «невидима» — это визуально. Практика: поставьте border на все элементы — «увидите» границы. Понимание «ящика» — 90% вёрстки. Соседи дружат ритмами. Оформляйте «дышащие» карточки: 16px padding, 1px border, margin 8. Бокс-модель — «грамматика» CSS. Изучайте на чужих макетах: «отступ где?» — мгновенно. Ваши ящики под контролем. Мастерство — в числах.
Имя в тени: тёмная тема и контраст в деталях
Тёмная тема — не «инверсия»: меняйте «светлоту» фона и «тусклость» текста. Красные «не» превращайте в «кричащие». Контраст — WCAG: 4.5:1 для текста, 3:1 для крупного/UI. Проверка contrast checker (WebAIM). В тёмном: яркие акценты «мягчить». background #121212, текст #eee. Не «чистый» чёрный (#000) — «неестественно» и «ореол» на OLED. box-shadow «тонет». Скринридер «не видит» тему — семантика неизменна. Медиа prefers-color-scheme: dark. Почитайте: «тёмная» тема для ночного чтения. Проверяйте гармонию: тень vs фон, разделители чуть светлее. Доступность — «мудрость»: не «тёмный фон = модно», а «комфорт глазам». Внимание: формы «нативные» — color-scheme. Каскад медиазапросов. Сделайте демо-карточку на тёмном фоне и проверьте контрасты. Практика: палитра Night mode для урока. Инклюзивность — выбор «и» для «ночных сов». Ваша страница теперь живет и «после заката». Разумная и «тёмная» красота — доступна всем. Светите акцентами, не «слепите» текстом.
Шрифтовая пара: system-ui без скачивания — скорость
System-ui — «родной» шрифт устройства: font-family: system-ui, -apple-system, «Segoe UI», Roboto. Ноль запросов за файлом — «мгновенная» отрисовка. Скринридер не поёт о гарнитуре, но «читабельно» важно. Для «веб-шрифта» вешайте «display: swap». Практика: body { font-family: system-ui }. Заголовки — «семейство» родное, жирнее. Не «тяните» 5 начертаний — «вес» страницы. Современный минимализм: system в основе. Производительность — часть доступности. Настройки юзера: ему виднее. «Быстро» = «уважение». Проверьте мобильный. Дисциплина шрифтов — профессионализм.
Типографика строки: line-height и ритм чтения
line-height задаёт «высоту» строки: норма 1.4–1.6 для текста. Короткие строки — диапазон шире; длинные — ближе. Скринридер не о пропорциях «поёт», но глазам важна. Практика: body { line-height: 1.6 }. Заголовки — плотнее (1.2). Отступы между абзацами — отступ. «Воздух» вертикальный — ритм страницы. Слишком «сильный» интервал рвёт связку строк. Соотношение: 30–45 символов в строке идеально. Выравнивание текста: left, не justify (дыры). Проверьте на мобильном зум. Читабельность — забота о пользователе.
Живая типографика: clamp() — размер без брейкпоинта
clamp(min, prefer, max) «резинит» размер: font-size: clamp(1rem, 1rem+1vw, 1.5rem). Между минимумом и максимумом — плавно. Скринридер не замечает, но «зум» корректен. Практика: заголовки через clamp — меньше media-запросов. Не «фетиш» на clamp: база rem, потом clamp у крупных. Ограничение: слишком «широкий» диапазон — крик. Для текста тела оставьте читаемый размер. «Быстрый» сайт + «живые» заголовки. Проверьте на десктопе и телефоне. Плавность — признак зрелости. Сдержанно и точно.
Пробел по-русски: nbsp и правильная типографика
Неразрывный пробел «держит» слово и число вместе: «10 кг». Скринридер читает как пробел. «Висячие» предлоги «не» красивы: перенос «на» строку режет смысл. Практика: «№ 5», «2025 год» с nbsp. Кавычки «ёлочки» для русского: «текст» (не «лапки»). Тире длинное «—», без пробелов? — по правилам. «Пробельная» типографика — признаки культуры. Сквозь строки: «не переносите» наречия. Проверка зрения: текст «не плачет» краями. Аккуратность с пробелами — уважение к читателю. Форматирование языка = манера письма.
Смысл через цвет: кнопка не только красная
Цвет «несёт» информацию: ошибка — красная, успех — зелёная. Скринридер не «озвучит» оттенок: дайте текст «и» иконку. Не «только» цветовой сигнал (WCAG 1.4.1). Практика: у сообщения ошибки — красная рамка «и» слово «Ошибка». Контраст: текст на фоне — проверяйте WebAIM. Дальтоники «видят» иначе. Цвет + символ + текст = надёжный сигнал. Доступность цвета — про смысл, не про «красоту». Проверка оттенков серой шкалой. Инклюзивность — решает отношение. Дисциплина контраста.
Единицы rem: масштаб и доступность зума
rem — «корень» (root), em — «родитель». rem «уважает» настройки масштаба браузера: увеличение «растёт» и текст. Скринридер не о единицах, но «зум» — доступность зрения. Практика: размеры/отступы в rem, em для «относительных» сущностей. Пиксели допустимы для «тонких» элементов — рамок. Осторожно: em «цепляется» — измените родителя, всё «едет». «Ритм» решётки держите в rem. Проверьте Ctrl+/Ctrl-: страница «не ломается» на 200%. Согласованный масштаб — здоровье раскладки. Доступность начинается с единиц.
Выравнивание форм: label в ряд под капотом
Горизонтальная форма (label «слева») — плотная, «табличная». Vertical — «дыхание с воздуха». Скринридер: связь label+input важнее геометрии. Практика: короткие поля (имя, город) — в ряд; длинный текст — столбик. Label «неразделим» с контролом. for/id — жёсткая связь. Группа radio/checkbox — fieldset. Выравнивание чисел справа в таблицах: text-align: right. Вертикальный ритм формы — сетка. Проверка: таб идет по порядку. Гибкость раскладки — уважение. Читайте, как «поток» движется. Аккуратность связей — семантика.
Пароль с глазами: шоу/хид и атрибут autocomplete
Поле пароля: type=password •••. Кнопка «показать» переключает type в JS. Скринридер: не сообщать тип «без» нужды. autocomplete=current-password/new-password — менеджер паролей поможет. Не «просите» пароль «по-глупому»: подсказка силы рядом. Практика: форма входа с «глазом». aria-label кнопке «Показать пароль». Тумблер визуальный + текст. Никогда «не» логируйте пароль. Связь label+input. Но UI: иконка «глаз» кликабельна. Новый пароль: minlength, required. Скринридер «прочтёт» подсказку. UX формы — безопасность без барьеров. Интуитивный контроль.
Ховер только на десктопе: media (hover: hover)
На сенсорных экранах «ховера» нет: касание «тап» вместо hover. @media (hover: hover) — стили для мыши, (hover: none) — для касаний. Скринридеру не «о чём» наводиться. Практика: меню на hover + фокус для клавиатуры; сворачивание на тач — по «тапу». Не «прячьте» контент только за hover — потеря на мобильном. Кнопки: min 44px для пальца. «Тонкие» состояния — декорация. Сделайте: и hover, и focus:visible. Проверьте на планшете. Адаптивные состояния — нервы интеракции. Доступность времени реакции.
Псевдокласс :focus-visible — умное кольцо
:focus-visible «показывает» кольцо только при клавиатуре (Tab), не при мыши. Это «память» стилей. Практика: кнопки с :focus-visible outline — клавиатурная навигация видна. Мышь не «мельтешит» рамкой. Не «убивайте» outline: он признак фокуса. focus (безусловный) тоже нужен, но… Для полей — видимый фокус всегда. Скринридер «услышит» переход фокуса. Компромисс: эстетика + доступность. Проверка: Tab по странице, Enter — работает. Дисциплина фокуса — вежливость. Псевдокласс современных браузеров. Включите в «базу».
Ссылка в «кнопочном» виде: роль в подвохе
Ссылка для перехода, кнопка для действия. Визуально можно «стилизовать» любую. Но роль aria «для» скринридера не «обманывайте»: a с onClick не «кнопка». Практика: «Подробнее» — cсылка, «Отправить» — button. Если у «кнопки» нет действия кроме навигации — . Роль role=button на a — «костыль», избегайте. Не «вешайте» обработчик на div — семантика страдает. Скринридер «встречает» по . Принудительный tabindex отрицательный — «не». Аккуратность сущностей. Разделение «маршрут/действие» — ясность. Проверка: Enter и пробел. Семантика — дисциплина.
Состояние disabled: не только серость кнопки
disabled «вырубает» контрол: клик, фокус, ввод — недоступны. Скринридер «сообщит» disabled. Практика: submit заблокирован до валидации. Но: disabled «не» в фокусе — пользователь не «узнает» почему. Лучше aria-disabled=true на «живой» кнопке + подсказка. Не скрывайте «что» требуется: сообщение рядом. Стили disabled — сниженный контраст легальны, но «заметность» важна. Форма с disabled полем: объясните причину. Проверка: фокус, Tab, Enter. Милосердие UX: нельзя — скажите «почему». Состояния — словарь интерфейса. Доступность состояний.
Тег picture: арт-дирекшн изображений
<picture> выбирает <source> по условиям (media, type) + <img> запасной. Практика: разные кадры для десктопа/мобильного (широкий vs вертикальный). Скринридер «смотрит» на img alt — picture «не» мешает. Alt «у» img обязателен. Форматы: source type=image/webp/avif с фолбэком img/jpg. «Не» «перегружайте» picture: только если кадр реально другой. Быстродействие: подходящий размер. Проверка: DevTools — какой выбран. Атрибут loading=lazy на img. Адаптивные картинки — современный стандарт. Меньше байт, лучше опыт. Арт-дирекшн в чистом HTML.
Закругление и тень: CSS для «карточного» юмора
border-radius + box-shadow «взбивают» «карточный» стиль. Практика: карточка курса со скруглением и мягкой тенью. Скринридер «не видит» красоту, но «плоскость» не мешает. Не «злоупотребляйте» тенью: лёгкая, смещение вниз. border-radius: 8-16px «дружелюбно». Внутренние элементы: и radius наследования. Сетка карточек — gap. Ховер: поднять transform: translateY(-4px). Balance: тень «глубина». Семантика: article в карточке. Проверка контраста текста на фоне. Аккуратные тени — признак знания. Разделяйте «смысл» и «декор». Уют интерфейса.
Тень-фокус: outline-offset для чёткой границы
outline-offset «отодвигает» кольцо от контента: outline + offset 3px — видимость на любом фоне. Практика: фокус на карточках-кнопках. Скринридер «показывает» фокус не visual, но порядок важен. outline «вне» бордера не «режется» скруглением — но «снимается» с extent. offset «даёт» зазор под тенью. Комбинация: «кольцо» + тень — современно. Кастомный фокус через box-shadow «адаптируется» к радиусу. Проверка: Tab — видно ли на белом/тёмном. Фокус — «дорожный знак» пользователя. Не «стирайте» его. Обрамление уважения. Точность доступности.
Тег abbr с title: расшифровка сокращений
<abbr title=«полное»>сокр</abbr> — расшифровка по наведению/фокусу. Скринридер «прочтёт» title (частично). Практика: «HTML», «CSS», «API» в тексте — оберните. Кавычки «не» вокруг. Для «массовых» аббревиатур — первый раз расшифруйте. title дублирует содержимое — «не» «пустой». У первого: <abbr title=«HyperText Markup Language»>HTML</abbr>. Скринридер: название читается. Не злоупотребляйте — шум. Доступность терминов: знание читателя. Проверка hover: всплывает. Точность: регистр большой. Сокращение без расшифровки — барьер. Забота о языке.
Метаописание: description — анонс в выдаче
meta name=description — «анонс» в результатах поиска: 150-160 символов, суть. Скринридер на странице не «слышит» (это для роботов), но клик решает. Практика: 1–2 предложения, ключевые слова, призыв. Не «пишите» кликбейт-ложь. Каждая страница — своё описание. Кнопка «Подробнее» — не «для описания». В «выдаче» Google дополняет/обрезает. Проверка: у всех страниц description. SEO + пользователь: ясно, чем счёт. Доверие в 160 символах. Точность продвижения. Доступность смысла «до» клика. Компромисс «краткости».
Поле с подсказкой: helper-text и aria-describedby
Подсказка под полем «объясняет» требования: aria-describedby=«id» связывает. Скринридер «прочтёт» подсказку после ввода. Практика: поле пароля с требованием «8+ символов». Не путать с label: label — название, help — разъяснение. id уникален. Множественные подсказки — «два» id через пробел. Стиль подсказки: мельче, серо. Проверка: фокус — подсказка озвучена? (JAWS/NVDA). Ошибки: aria-describedby указывает на сообщение об ошибке. Динамика: JS обновляет. Дисциплина: у сложных полей — помощь. Доступность «почему» всегда. Ясность форм — забота.
Сегодня: input type=date и «стрелки» календаря
<input type=date> — нативный календарь: picker в браузере. Скринридер «построчно» читает день/месяц/год. Практика: поле «Дата рождения». Атрибуты: min, max, value. Формат доставки ISO (yyyy-mm-dd) — сервер рад. Стилизация picker ограничена — c «регулярным» дизайном. «Тач» — удобно. «Десктоп» — ввод вручную. Валидация встроена. Не «изобретайте» календарь с нуля — нативный доступен. Проверка: скринридер + клавиатура. Региональный формат — locale браузера. Простота календаря. Меньше кода — надёжнее. Формы будущего.
Карточка с полями: сгруппированная форма внутри
Форма может жить «в» карточке: логическая группа полей. Практика: «Доставка», «Оплата» — карточки-секции. Скринридер «поймёт» по legend/заголовку. Не «плодите» формы: одна на страницу лучше (иногда 2). Каждая секция — fieldset+legend. Поля связаны c label. Контекст «сверху» в заголовке. Осмысленные подписи. Кнопки действия — по месту. Проверка: tab по всей группе. Адаптив: карточки в столбик. Сгруппированный смысл — доступность. Ясная структура форм. Профессиональная сборка. Интуитивность по группам.
Ширина полей: max-width и «дышащая» форма
Не «растягивайте» поле до конца экрана: input { max-width: 480px }. Практика: форма авторизации по центру, поле не «печатает» на века. Скринридер не «видит» ширину, но «взгляд» читателя расслаблен. Короткие поля (номер карты) — «не» «размахивайте». Поле с 1 символом — унизительно. Баланс: форма по центру, метки слева. Проверка на «огромных» мониторах: не «ширится» на всё. Адаптивность: max-width спасает. Минимализм доступа. Для «длинных» комментариев — textarea шириной. Интерактив «воздух». Уважение пропорций. Центрирование — эстетика.
Невидимые label: скрытый, но доступный текст
Если визуально метки нет (иконка поиска), скройте label «по-хуже»: .visually-hidden (не display:none!). Скринридер «прочтёт», зрение — чисто. Практика: иконка-лупа с hidden-меткой «Поиск». display:none убивает доступность. Класс «скрытый» — позиционирование с клипом. aria-label дублирует? — «один» источник. Запасной вариант: placeholder — «не» замена! placeholder растворяется. Проверка: скринридер слышит метку «Поиск». Соответствие: имя у поля всегда. Скрытые метки — когда «умышленно» скрыто. «Скринридерный» минимум. Точность доступности форм.
Сетка из «двух» полей: имя и фамилия в ряд
Пары полей (имя/фамилия) в grid: две колонки, gap. Практика: регистрация с половинками. Скринридер «по порядку»: label, поле, label, поле. Каждая метка — своя (for/id). Не «одна» метка на «две» ячейки. Адаптив: на узком — в столбик (grid-template 1fr). Veritcal stacking на мобильном. Заполнение: автокомплит. Проверка: нет ли «перепутанных» подписей. Горизонтальные пары экономят место, но… «дыхание» чтения. Дисциплина: этикетки не «рвутся». Формы-двойни — аккуратно. Комфорт ввода. Место и смысл.
Свежий взгляд: предзаполненное поле с placeholder
placeholder «подсказывает» пример («Иван Петров»), но «не» заменяет label. Различие: label всегда, placeholder исчезает при вводе. Практика: пример как placeholder + видимая метка. placeholder не имеет «родного» for. Скринридер «слышит» label. Не «пишите» в placeholder «Введите…» (label уже говорит). Ошибка: placeholder вместо label — провал валидации при пустом. Проверка: пусть placeholder будет подсказкой-примером, не «именем». Стиль «плейсхолдера»: серый, курсив — отличие. Чем «меньше» когнитивной «нагрузки» — тем лучше. Примеры в помощь. Ясность ввода.
Интерактивность: hover-подсказка через title на ссылке
title на элементе «всплывает» подсказкой при наведении/фокусе. Скринридер «прочтёт» (не всегда). Практика: у неоднозначной ссылки title=«детали». Не «дублируйте» текст: title повторяет link text — шум. Для «скринридера» лучше текст ссылки понятен сам. Когда title уместен: уточнение, формат файла (PDF), открытие в новом окне. Не «срывайте» доступность. Проверка: фокус — всплывает? (мышь фокус нет). «Точечные» подсказки — тонкость. Читаемость ссылок — base. Краткость и польза. Аккуратность подсказок. Не «наращивайте» всплывашки везде — «крик». Значение точности.
Группа-мольберт: fieldset вокруг опций даты
Дата «в» группе: день/месяц/год select — fieldset+legend. Практика: «Дата рождения» тремя селектами. Скринридер «встретит» legend — место «входа». Каждый select — label (for/id). Не «плодите» третий select когда можно date input. Но «очень» специфичные комбинации — так. Вертикальный порядок важен. Нюанс: удаление лишних — good. Проверка: фокус в группе в порядке. Автокомплит даты. Доступность группы — через legend. Объединение смысла. Раздельный ввод сложных полей. Ментальная модель: «всё про дату». Ясność сгруппирована.
Одна форма, два энтерпойнта: первое поле в фокусе
Автофокус (autofocus) на главном поле ускоряет: пользователь сразу печатает. Осторожно: autofocus «крадёт» старт у скринридера? — избегайте на больших страницах. Практика: поиск в шапке — autofocus уместен? Для «мобильного» — «не». Скринридерная навигация: автофокус дезориентирует. Методы: первая ссылка контента. Лучше «таб» в контент. Не «перебивайте» пользователя. Проверка: скринридер встречает форму сразу? Нежелательно. Критерий: важность поля. Тонкость: не автозаполняться без нужды. Баланс «удобства». Уважение к темпу. Автофокус — «инструмент» с мерой.
Случайный порядок: tabindex положительный — осторожно
Положительный tabindex «перемешивает» поток таба: tabindex=1 идёт первым. Это «сшибка» источника: документ порядок ломается. Практика: почти никогда не нужен. Скринридер «идёт» по tabindex — бессистемный скачок дезориентирует. Правило: нулевой/отрицательный tabindex — да; положительный — «красный флаг». Порядок = порядок документа. Перестановка визуальная не «порт» читается. flex/grid могут «перерисовать» отображение — используйте «source order». accessibility tabindex: -1 для программного фокуса (JS-модалки). Дисциплина: сохраняйте логику чтения. Проверка: Tab последователен. Простота — добродетель.
Ссылка внутри параграфа: интерактивный акцент
Ссылка в тексте «сливается» с предложением: контекст понятен. Скринридер «прочтёт» имя ссылки в контексте. Практика: «Подробнее в справочнике». Не «ссылайтесь» на «здесь»/«тут» — плохое имя. anchor text = цель ссылки («справочник»). Не «накручивайте» длинный текст. Глазу: подчёркивание (дефолт) vs кастом (hover-подчёркивание). Контраст ссылки — 3:1 min. Отличие от текста «не» только цветом. Практика: осмысленные короткие ссылки в абзацах. Проверка: скринридер-список ссылок — нормальные имена. Ясность «выходов». Читабельность инлайн-интерактива.
Приятные мелочи: transition на полях форм
Анимация на фокусе input «успокаивает»: border-color плавно. transition: border-color .2s. Скринридер не видит, но «гладкость» радует глаз. Практика: фокус поля — мягкое выделение. Не «разгоняйте» на всё: transform/opacity безопасны. Умеренность: 150-300ms. Кастом цвет фокуса вместо резкого. Не «мелькайте» — утомление. prefers-reduced-motion: отключить. Проверка: «дышит» ли интерфейс. Плавные формы — молодость интерфейса. Дисциплина анимации. Простота переходов. Комфорт восприятия.
Тень удачи: карточка с border и фоном-подкладкой
Карточка «стоит» на фоне секции: section { background:#f8f9fa } + card белая. Практика: сетка курсов на сером полотне. Скринридер «не» различает, но «иерархия» визуальна. Контраст тени на фоне. Border-radius: 12px. Внутренние отступы: padding. Тень «там, где карточка» отделяется от фона. Грид-гэпы. Вложенные поля — аккуратно. Проверка контраста текста. Пространственная иерархия — сигнал. Аккуратные границы — профессионализм. Воздушная композиция. Семантика: article в карточке. Функциональная эстетика.
Слово «и» в заголовке: заглавные — не «криком»
Заголовки «не» «кричат», а «говорят». ЗАГЛАВНЫЕ в заголовке — крик, скринридер «прочтёт» буквы как слово? — да, но стиль… Практика: «нормальный» регистр с «правильным» акцентом. Шрифты: вес/размер разрешают «тихо» выделить. Слова «с» заглавной — не «используйте» безмерно. КАПС для акцента «одного» слова — ок «в» малом. Проверка: длинный капс труден для чтения (дислексия). Типографика: smaller caps для иронии. Дисциплина «тишины» в тексте. Уважение читателю. «Величавость» — через интервалы. Аккуратный регистр. Читаемость = доступность.
Отступ «уютный»: margin для сгруппированных блоков
Вертикальные отступы «устанавливают» ритм. margin-bottom «разделяет» абзацы; «margin-top» «void» — кроме перв. Скринридер «не оgap», но «темп» глаз понимает. Практика: p { margin: 0 0 1rem }. Последовательность отступов — повторяемость. Не «собирайте» мусор из марджинов в одну кучу. Используйте flow-отступы (margin к следующему). «Не» обязателен «одинаковый» напр. ВАЖНО: марджин «сливается» (схлопывание) — знание. Проверка: глазами «дышится». Дисциплина ритма. Отступ «внутри» — padding, «между» — margin. Пространство — тишина кода. Единый язык вертикали.
Центрирование по-взрослому: flex и логика
Центрирование «блока» внутри секции: body «полоса» flex? Практика: центрируем карточку, форму, логотип. display:flex; justify-content:center; align-items:center — и высоты. Скринридер не «видит» геометрию, но «порядок» читается. Не «мучайте» margin:auto «без» нужды? — но это тоже способ. Вертикальное центрирование — flexbest. Для «одной» строки — line-height трюк. Проверка: на разной высоте окна — стабильно. Дисциплина: центрируем «правильно», с пониманием. «Выравнивание» = «гармония». Сетка — структура. Но «центр» не всегда «лучше» (текст — left). Осознанный выбор.
Фон и текст: контраст «не» жертва декора
Фон «красивый» (градиент, фото) «может» съесть текст. Скринридер «не» о фоне, но «читаемость» страдает. Практика: текст на фото — с плашкой/градиентом поверх. Контраст 4.5:1 (текст), 3:1 (крупный). «Overlay»: rgba(0,0,0,.45) под текст. Не «полагайтесь» на «светлый» фон. Проверка: WebAIM contrast checker. Обход: светлая полоса. Бизнес: текст читается всегда. Эстетика в рамках доступности. Затемнение «разумно». Аккуратный баланс «красоты» и «смысла». Контраст — право читателя. Дисциплина оформления.
Поля форм: свежий взгляд на высоту
Клик по полю «попадает»: «зона касания» 44px min. Практика: input { height: 44px }. Загадка «тонких» полей: промах мизинцем. Скринридер не «вплотную», но «большой палец» благодарен. У кнопок — то же. «Не» «микросайт» в 20px. Мobile-friendly — это удобство. Высоты едины в форме — ритм. Поля «рядом» друг с другом: без «лишнего» gap. Проверка на сенсоре пальцем. Дисциплина размеров. Когда «мелкие» уместны (десктоп-утилиты) — компромисс. Доступность точности касаний. Уважение к рукам.
Позиционирование: sticky-шапка поверх контента
position: sticky; top:0 — шапка «прилипает» при скролле. Скринридер «не» о «залипании», но «навигация» всегда видна. Практика: меню-шапка sticky. Учесть: фон непрозрачный (чтобы текст «не» просвечивал). Отступ сверху у контента. Проверка: контент «не» прячется под шапку. Sticky «в» пределах родителя. Не «ploди» sticky-в-столбик. На мобильном «меню-бургер» в sticky. Адаптив сочетает. Вертикальный баланс. Ссылки доступны всегда. «Закрепление» = польза. Но «не» «крадите» ~60px у контента разумно. Дисциплина окна.
Заголовок внутри figure: подпись и семантика
figure+figcaption «паспорт» иллюстрации. Можно ли «внутрь» заголовок? — «не» «обязательно»; figcaption уже «имя». Практика: img+figcaption «График 1». Скринридер: figcaption «как» подпись. Не «дублируйте» h3 «над» figcaption — шум в навигации. «Заголовок» фигуры = figcaption. Для «раздела» с фигурами — секция с h2. Структура: figure самодостаточен. Рисунок «смысловой» в статье. Проверка: порядок оглавления чист. Семантика «рисования». Краткая подпись. Осмысленная. Каждая фигура «представлена». Не «взвешивайте» лишними h. Чистота списка заголовков.
Разделители «элегантно»: hr и его значение
<hr> — «тематический» разрыв между разделами (не «линейка-декор»!). Скринридер «пауза» между темами. Практика: hr между «Интро» и «Глава». Не «пользуйтесь» hr для простой линий декора — use border. WAI-ARIA: hr — «разделитель». Стиль: тонкая линия, отступы. «Не» «встаньте» hr «в» середине логической связи. Проверка: скринридер слышит «прерывание». Простота: .separator может заменить. Семантический разрыв контента. Доступность «пауз». Аккуратность структуры. Не злоупотребляйте «линеатурами». Осмысленный «воздух» глав.
Выделение в тексте: mark корректно
<mark> «подсвечивает» релевантное: совпадение поиска, акцент. Скринридер «прочтёт» без особой интонации? — «да». Практика: в результатах поиска выделить совпадение mark. Не «сортируйте» mark «для» цвета — эм не для того. mark «жёлтый» по умолчанию сменен кастом. Много mark = «крик». Проверка: mark в «прогрессе» чтения. Семантика: маркировка «важности» (скринридер голосом?). Для «эм»/«strong» — различие: strong — важность, em — ударение, mark — соответствие. Аккуратное применение. Фон mark не «убивает» контраст. Доступность выделений. Точность значения.
Списки «сложные»: ol вложенный нумерация
Вложенный ol «нумерует» иерархию: шаги с под-шагами. Скринридер «прочитает» уровни. Практика: инструкция «с» подпунктами. start= задаёт старт: start=2 «продолжает». reversed — обратный счёт. Не «смешивайте» уровни «случайно». Не «ломайте» нумерацию визуально, если семантика — ol. Каждый li — элемент. Листинги упорядоченные — «когда» важна последовательность. Не «переделывайте» 1. на «—» «вручную». Проверка: Nested ol валиден? — да. Знак «иерархии» — глубина. Семантика «умных» списков. Диапазоны «просты». Аккуратность структуры «данных».
Текст-обёртка: first-letter и стили «кап»
::first-letter «украшает» первую букву абзаца (буквица). Практика: роман-зачин с большой буквой. Скринридер «не» об этом — но «чтение» элегантно. Не «переусердствуйте»: буквица «в» правовой странице? — нет. ::first-line — первая строка. CSS-псевдо — декорация, «не» смысл. Проверка: contrast «буквицы». Здоровая мера приёма. Буквица крупная, float. Ограничение: only block. Осознанная «красивость» глав. Дизайн и читабельность «вместе». Не «засоряйте» текст. Эстетика первой буквы — деталь мастера. Сохранность доступности.
Выделение мышью: ::selection и фирменный цвет
::selection задаёт цвет «фона/текста» при выделении. Практика: маркер-акцент под бренд. Скринридер не «озвучит» цвет, но «ритм» глаза важен. Не «ломайте» контраст: текст+фон в паре. Не «убирайте» выделение вовсе — сложно копировать. Практикуйте: кастом «выделения» в статьях. Каскад: ::selection «наследуется» с body. Доступность: «не» «сливайте» bg с текстом. Проверка: кисть по тексту — читаемо ли. Эстетика «аккуратного» маркера. Мера: одна «тёплая» подложка. Осмысленное акцентирование. Глаз любит порядок. Скорость чтения при выделении. Уважение к жесту. Тонкость деталей типографики. Дисциплина «спокойных» атрибутов.
Хлебные крошки: путь навигации по сайту
Хлебные крошки показывают «где» вы в иерархии: Главная / Каталог / Кроссовки. Практика: страница товара с тремя уровнями. Скринридер «прочтёт» список ссылок; навигация aria-label=«Хлебные крошки». Разделитель «/» » — семантически лишний, скройте (aria-hidden или CSS). Не «разбивайте» текущий пункт ссылкой — просто текст. Практика: nav + ol + li. Каждый уровень — ссылка «назад». Проверка: порядок от «корня» к «листу». Доступность: «полный» путь без кликов. Удобство «возврата». Иерархия «ясна». Не «плодите» крошки где «без » 2 уровней. Дисциплина навигации. Простота ориентиров.
Пограничный случай: перенос длинного URL в тексте
Длинный URL «ломает» верстку: overflow-wrap:anywhere / word-break:break-word мнут строки. Практика: ссылка-адрес в письме/статье. Скринридер «прочтёт» весь URL — «не» «режьте» его aria- «не». Стиль: overflow-wrap:anywhere на a в контенте. Гиперссылка «не» «выплескивается» за блок. Мобильный: «не» «едут» колонки. Желание™: разбить по «/»? — CSS. Проверка: узкая колонка — ссылка влезает. Доступность: «куда» ведёт — видно «до» клика (title/текст). Дисциплина: сокращайте видимый текст, но «сохраняйте» href полный. Комфорт «длинных» ссылок. Читабельность адреса. Аккуратный перенос. Уважение к строке. Простота контента.
Числа и таблицы: выравнивание вправо
Числовые данные в таблицах выравниваются вправо — «визуальная» колонка сумм. Скринридер «знаком» с числами; выравнивание гармония. Практика: бюджет, ведомость. th — заголовок колонки; числа td правым краем. Десятичные точки выровнены (tabular-nums). Скринридер не «дергается» о выравнивании, но «взгляд» сравнивает. Проверка: alignment «в» колонке единый. Summing вниз — line. Доступность: контраст цифр. Не «центрируйте» числа в таблицах — «теряется» сравнение. Дисциплина чисел. Аккуратная колонка данных. Мера: join с «отчетами». Читаемость цифр — уважение. Простота финансов. Осмысленная сетка таблицы.
Один такой: :only-child для «единственного»
:only-child — единственный ребёнок родителя. Практика: «пустая» строка таблицы, пустое состояние списка. Скринридер «не» знает CSS-селектор, но «контент» читается. Практика: уведомление «без» соседей. Не «навешивайте» :only-child для декора. Данные динамичны — состояние важно. Псевдокласс «экономит» классы в DOM. Не «путать» с :first-child/:last-child. Скринридер: читает естественно. Проверка: визуально один — стиль. Меньше «мусора» в разметке. Доступность «пустоты». Ясные пустые состояния. Осознанный CSS-выбор. Чистота селекторов. Профессиональный минимализм. Семантичные псевдо.
Горизонтальные табы: семантика вкладок без JS
Табы из чистого HTML «без» JS сложны. Практика: скорее «аккордеон» details или «якорные» секции. Скринридер: настоящие вкладки — role=tablist/tab/tabpanel с активным состоянием (ARIA). Не «стройте» «псевдо-табы» на click без ARIA — обман. Проще: вкладки как «якорные ссылки» к секциям. Tab-клавиша «не» «входит» в «роль» правильно без tabindex=-1 (JS). Реализм: «без» JS держитесь кнопок-гиперссылок и «видимой» секции-выбранной. Проверка: скринридер «читает» активную. Доступность вкладок — дело ARIA-дисциплины. Компромисс: аккордеон. Осознанная семантика. Простота vs «эффект». Честность состояний.
Смеси блока: padding против gap внутри карточки
Внутри карточки: padding «дышит» от края; gap — между дочерними. Практика: карточка статьи: заголовок, отступ, текст. Скринридер не видит пробел, но «композиция» ясна. Не «путать» margin (снаружи) и padding (внутри). Практика: два способа сделать «воздух» внутри. Вертикальный ритм: margin-bottom элементов. Проверка: переполнение при росте контента. flex/grid gap позволяет «не» «вешать» margin на первый элемент. Скринридер «не» о gap. Доступность: контент не «слипается». Дисциплина отступов. Чистый ритм карточки. Осмысленное пространство. Экономия CSS. Гармония блока. Профессионализм в деталях.
Заголовок и время: тег time в статье
<time datetime=«2025-03-14»>14 марта</time> — машиночитаемая дата. Скринридер «прочтёт» текст; machine — datetime. Практика: дата публикации в блоге. «Не» «прячьте» время в текст. Формат ISO для машины, человеческий — для глаз. time <time> — только дата/время, не «длительность» события без времени? — можно. Проверка: datetime корректен, парсер поймёт. Скринридер «не» «путает». Доступность «свежести». Практика: публикация+обновление. Метаданные в потоке. Точность даты. Дисциплина времени. Профессионал «подписывает» момент. Место: в шапке статьи. Ясность «когда» для всех. Аккуратная мета.
Заголовок как кнопка: подвох в деталях
Заголовок accordion-секции обычно <button> внутри заголовка — «не» заменяет h. Практика: details>summary — нативный аккордеон, где summary «спрятан»? Нет. summary — заголовок «виден». Реальность: h внутри button? — «не» валидно (button flow content). Практика: summary с CSS. Скринридер читает summary как «раскрыватель» (aria-expanded). Не «плодите» «кликабельные» заголовки без состояния. Проверка: клавиша Space «раскрывает». Больше — details/summary «без» JS. Доступность аккордеона. Осмысленный заголовок-интерактив. Гибкость семантики. Честный интерактив. Дисциплина структурных тегов. Простота открытия.
Команда margin: горизонтальное выравнивание
margin: 0 auto — центрирует блочный элемент с шириной. Практика: форма, колонка, логотип. Скринридер не о геометрии, но «пустое» поле по бокам гармонично. Не «запирайте» автора. Скринридер «не» «более» равноправен. Практика: max-width + auto — «мягкий» центр. Проверка: только при явной ширине. Переполнение: box-sizing. Доступность центров «не» влияет на чтение. Дисциплина: margin auto для «одного» центрируемого. Полная ширина? — «auto» «0». Вложенные — аккуратно. Вертикальное центрирование иначе (flex). Простота «резины». Осмысленная композиция. Уважение к полям. Гармония страницы. Чистый CSS-жест.
Переключатель света: тёмная тема через CSS
Тёмная тема: media (prefers-color-scheme: dark) задаёт другие переменные. Практика: :root — свет, @media dark — тёмный. Скринридер не «о теме», но «глазу» легче ночью. Не «жгите» глаза белым. Переменные + prefers-color-scheme. Проверка: переключить тему ОС — сайт «отзовётся». Контраст в тёмной теме: чёрный фон + тёмный текст? — «нет», #111+#eee. Аккуратно с тенями (в тёмной — «светлее»). Скринридер ничего. Доступность выбора. «Не» только «авто» — дайте кнопку. Дисциплина палитры. Осмысленная тьма. Комфорт чтения. Современный стандарт. Уважение к режиму пользователя. Гармония фона.
Выравнивание по сетке: baseline у списков и текста
align-items: baseline — элементы «опорной» линией текста. Практика: label «рядом» с инпутом выровнены по тексту. Скринридер не о CSS, но «взгляд» приятен. Не «теряйте» ось текста — baseline гармонирует. Практика: списки курсов с ценой и названием. Проверка: старт «в» строке. flex/grid align-items. Скринридер не заметит — «база» восприятия. Доступность ритма: нет «скачков». Дисциплина выравнивания. Профессиональная композиция. Осмысленная ось. Простота глаза. Читабельная сетка. Уважение типографики. Точность верстки.
Между заголовком и абзацем: lead-параграф
• Лидирующий абзац — «вступление»: крупнее, ослаблен весом, сразу суть. Практика: статья с первым-более-заметным абзацем. Скринридер «чист» — но «взгляд» ловит смысл. Не «увлекайтесь»: lead — 1 абзац, не «5». Класс .lead со стилем. «Не» «вздувайте» размер до заголовка. Мораль: подпис-интро. Проверка: контраст текста. Доступность «начала». Практика длинных статей. Простой приём «входа» в материал. Дисциплина визуальной иерархии. Осмысленный акцент абзаца. Читатель сразу «в теме». Осознанная типографика. Уважение к читателю. Краткое «зерно» статьи.
Курсор-помощник: pointer на интерактиве
cursor: pointer на кликабельном — «сигнал» руки. Практика: кнопки, ссылки, переключатели. Скринридер не «видит» курсор, но «мотив» ясен. Не «вешайте» pointer на не-интерактив. Проверка: div с onclick — нужен role/таб. Cursor default на тексте. Не «злоупотребляйте»: pointer только где «жмётся». Тонкость: на дизейбл-кнопке cursor: not-allowed. Каскад переходов. Практика: кнопка-ссылка. Скринридер «не» о курсоре. Доступность: кликабельность «понятна». Дисциплина курсора. Интерфейс «отвечает» на движения мыши. Визуальный намёк интерактива. Простота сигналов. Уважение к жесту. Честная кнопка. Гармония UI.
Видимость рамок: border и radius вокруг полей
border поля виден «полем» формы; border-radius скругляет. Практика: input с мягким радиусом + спокойной рамкой. Скринридер не о декору, но «поле» распознаётся по label. Не «убирайте» рамку вовсе — граница «говорит». Не «спорьте» с требованием вводе. Проверка: контраст рамки. focus — меняет цвет рамки. Практика: серая рамка → акцентная при фокусе. Доступность: видимое «поле ввода». Дисциплина границ. Осмысленная рамка. Мягкий радиус (4–8px). Тонкость стилизации. Профессиональная форма. Уважение к деталям. Гармония ввода. Чистый контур.
Скорость чтения: колонки и ширина текста
Оптимальная ширина текста — 60–75 символов на строку. Практика: статья с max-width контента. Скринридер не «не» „заснул“, но длина строки «играет» для глаз. Не «растягивайте» абзацы на весь монитор. Проверка: слишком длинные строки «устали» взгляд. Доступность «линии». Скринридер «не» о средстве. Практика: max-width: 65ch на секции. Дисциплина «ширины» чтения. Уважение к движению глаз. Мерное насыщение. Осмысленный простор. Осознанное «поле» для текста. Читаемость вне зависимости от монитора. Комфорт абзаца. Профессионализм типографики.
Определённый хлеб: дефиниции через dl
<dl> (список определений) — термины + определения: dt + dd. Практика: глоссарий, параметры товара. Скринридер свяжет? — «да», порядок чтения. Каждый dt имеет dd. Не «путайте» с ul/ol (они «списки», dl — «пары»). Практика: «Диагональ» — dt, «15.6″» — dd. Доступность: скринридер «прочтёт» пару. Не «вставляйте» dl внутрь текста «для» декора. Проверка: ассоциация пары. Множество: несколько dd к одному dt — можно. Дисциплина «определений». Осмысленный глоссарий. Чистая семантика. Уважение терминов. Простота структуры. Профессиональный словарь. Ясность близнецов-пар.
Ссылка целиком: stretched-link с фокусом
Ссылка «растягивается» на всю карточку: позиционируем «псевдослой» поверх. Практика: карточка товара, вся «кликабельна». Скринридер увидит «настоящую» ссылку (не спан). Не «дублируйте» ссылок вокруг — одна. Проверка: фокус попадает на ссылку. Практика: article>a.stretched. Доступность: одна цель клика. Не «разбивайте» клик по «зонам». Дисциплина: контент карточки не «должен» перекрываться ссылкой-псевдо? — используйте z-index на тексте. Скринридер: порядок чтения. Простота «большой» цели — удобство. Осознанная ссылочная область. Профессиональный паттерн. Гармония клика. Чистая разметка.
Поля label: связка «нажал на слово»
label с текстом — клик по слову переводит фокус в поле. Практика: чекбоксы с крупными подписями. Скринридер «читает» label как имя поля. Не «разрывайте» связь: for=id. Практика: radio «Настроение». Проверка: клик по тексту выбирает. Доступность: большая зона для касания. label.as-block для макета. Дисциплина: у каждого контрола — label. Скринридер: имя «прежде» ввода. Без label — «безымянное» поле. Осмысленная метка. Простой таргет-«между». Осознанная зона клика. Уважение к пальцу и клавиатуре. Профессиональная форма. Гармония подписей.
Маленький экран: стоп-кадр media-запросов
@media (max-width:600px) меняет макет под узкий экран. Практика: колонки в столбик, шрифт не меньше 16px. Скринридер «не» о пикселях, но «поток» чтения сохраняется автоматически (DOM-порядок). Не «ломайте» порядок визуальным переразмещением. Проверка: просмотр на 360px. Практика: «меню-бургер» на малом, полное на большом. Доступность: фокус не «прыгает». Дисциплина брейкпоинтов: раз, плавно. Осмысленная адаптация. Сохранение смысла. Простота мобильного «жеста». Осознанный сброс размеров. Уважение к многообразию экранов. Гибкая сетка. Профессиональный responsive. Гармония вида.
Псевдокласс empty: пустая строка без «хвоста»
:empty — элемент без дочерних узлов (даже «пробела»!). Практика: ячейка/маркер/«без» текста. Скринридер «не» особенно, но «пустоту» контролирует визуал. Не «оставляйте» лишние пробелы — :empty «не» сработает. Редкий случай: «точка»-разделитель. Проверка: «без» whitespace. Практика: пустое состояние списка.. Доступность: пространство «не» сбивает чтение. Дисциплина: не «мусорить» DOM. Осмысленная пустота. Чистая разметка. Простота селектора. Продвинутый CSS. Осознанная степень абстракции. Уважение к коду. Меньше «лишнего». Профессиональная точность.
Цвет ссылки: наследование и унаследованный вид
Ссылки по умолчанию — синие и подчёркнутые; «не» «теряйте» этот сигнал. Практика: смена цвета ссылок под палитру, но с контрастом и отличием от текста. Скринридер «прочтёт»; визуально «не» путайте с обычным текстом. Не «убирайте» подчёркивание без замены (hov/focus). Проверка: 3:1 к фону для link. Доступность: «понятно», что это ссылка. Практика: nav без подчёркивания, но с hover/focus. Дисциплина отличий. Не «нагибайте» весь текст в ссылки. Простая деталь. Осмысленный акцент. Гармония линка. Профессиональная стилизация. Уважение к привычке чтения. Чистота ссылок.
Кнопки-соседи: порядок в форме
Порядок кнопок: «основной» слева/первый в DOM? — для «жителей» LTR первичный слева, для валидности — логика. Практика: «Отмена» `Сохранить`? Скринридер читает по DOM. Осторожно с «везде-привычкой». Проверка: Tab — последовательно. Не «переставляйте» визуально (flex-order) против чтения. Доступность: фокус-порядок предсказуем. Практика: форма «Сохранить|Отменить». Дисциплина: первичное действие — первое «в» DOM/взгляде. Не «плодите» лишних кнопок. Осмысленный порядок. Уважение к сценарию. Простота действий. Профессиональный выбор. Гармония кнопок. Чистая логика формы.
Подпись к полю: «невидимый» label для поиска
Где визуальная метка не помещается (иконка-лупа) — «скрытый» label: класс visually-hidden, сохраняет доступность. Практика: поле поиска с aria-label. Скринридер «прочтёт» скрытую метку. Не «выключайте» label. Проверка: «лупа» с aria-label="Поиск". Доступность: поле имеет имя. Практика: .sr-only. Не «путайте» display:none (скрытая от скринридера). Дисциплина: метка «есть» всегда. Визуально — иконка/placeholder. Осмысленное имя. Простота доступа. Уважение к незрячему. Профессиональная форма. Гармония поиска. Чистая семантика. Лёгкость ввода.
Типографика списков: маркеры и отступы
У списков — свои «отступы»: padding-left у ul/ol рисует маркеры. Скринридер «не» о CSS-маркере, но «список» семантичен. Практика: list-style-position: outside. Не «убирайте» маркеры без причины (list-style:none где меню). Проверка: вложенность читается. Практика: читаемый список определений. Доступность «перечня». Дисциплина: маркеры помогают «глазу». Осмысленный список. Уважение к структуре. Простота перечня. Гармония пунктов. Чистый текст. Профессиональная разметка. Осознанный вид маркера. Лёгкость сканирования. Ясность списка.
Крайние поля: авто отступы и «воздух»
Отступы между соседями: margin-bottom вместо «margin-top у каждого». Практика: стопка статей, абзацев. Скринридер «не» о пробеле, но «ритм» глазом. Не «плодите» margin сверху и снизу — схлопывание сбивает. Проверка: одинаковый «шаг» по вертикали. Практика: gap для flex/grid колонок. Доступность «пространства». Дисциплина ритма. Единый «интервал» в композиции. Осмысленный поток. Простота макета. Уважение к чтению. Гармония «тишины». Профессиональный порядок. Чистые отступы. Лёгкость восприятия. Осознанная коллекция пробелов.
Ссылка-«Х» «в» конце индекса: архив-ряд из чисел
Ряд «страниц»: «1 2 3 … 12» + «Предыдущая/Следующая» <nav>. Практика: каталог с постраничкой. Скринридер «найдёт» nav-ориентир; relative-ссылки — «заголовки» осмысления. «Не» «разрывайте» ряд: red&-числа не «выпадают», если «не» ссылки — «span» с aria-current=page. Проверка: «Текущая» явно отмечена текстом/состоянием. Доступность «пагинации». Дисциплина «границ» ряда. Осмысленная «страница 1 из 12». Практика: «…» как span. Уважение к «дальней» навигации. Профессиональный «огрызок» чисел. Гармония «стрелок». Чистая «полка» страниц. Ясный «край» пагинации.
CSS-порядок в DOM: «поток» через source order
Визуальный flex/grid может «переставлять», но «чтение» идёт DOM-порядком. Практика: карточка: заголовок, текст, кнопка — «уже» в DOM «правильно». Скринридер «не» «прыгнет» по визуалу. Не «перестраивайте» markup ради «красоты» flex’а — сохраняйте «поток». Проверка: линейное «прочтение» без скачков. Доступность «порядка». Практика: «действие» последним в DOM. Дисциплина «семантического» потока. Осмысленная «очередь» блоков. Уважение к чтению. Профессиональная «центровка» без «ломания» смысла. Ясная последовательность секций. Гармония «источника».
Якорные «прыжки»: ссылка на секцию страницы
<a href="#code">К коду</a> + <section id="code">: якорь по странице. Практика: «оглавление» лонгрида. Скринридер «Tab» «не» о якоре? — «нет», но «ссылка» имя — цель. Не «ломайте» id (уникален). Проверка: клик — вниз к секции; фокус? — «должен» уйти к цели! Не «прячьте» target на странице. Практика: «К началу» в конце. Доступность «прыжков». Дисциплина «уникальности» id. Осмысленный «горизонт» лонгрида. Профессиональная «навигация по секциям». Уважение к длине. Лёгкость возврата.
Тег picture «не» «всегда»: просто img с srcset
srcset на img «сам» «выберет» размер по плотности/ширине: <img srcset="a.jpg 1x, b.jpg 2x">. Практика: retina. Скринридер «не» о плотности, но «контент» тот же. Не «тяните» picture «где» хватает srcset. Проверка: на retina берётся 2x. Доступность «резкости». Практика: декоративная замена. Дисциплина «весов» изображения. Осмысленный «ретина-режим». Профессиональная «чёткость». Уважение к экрану. Лёгкость кэша. Гармония «density».
Скриншот-«превью» «в» карточке: img + figcaption «с» alt
Скриншот интерфейса в карточке-портфолио: figure+figcaption, alt «описывает» «что» на скрине (если значимо) или aria-hidden+подпись (декор). Практика: кейс с превью. Скринридер «прочтёт» alt/подпись — «не» «огромный» текст. Практика: alt="Скриншот формы регистрации". Доступность «витрины» работ. Дисциплина «честного» alt. Осмысленный «кейс». Профессиональное «превью». Уважение к детали. Гармония «портфолио».
Переключатель темы: role=switch «настоящий»
Тумблер темы «светлая/тёмная»: button role="switch" aria-checked. Практика: header-контрол. Скринридер «прочтёт» состояние. Не «имитируйте» switch div-ом «без» роли. Проверка: Space — переключение, aria-checked меняется. Доступность «выбора». Дисциплина «двух состояний». Осмысленная «тема». Профессиональный «тумблер». Уважение к предпочтениям. Гармония «переключателей». Честное «вкл/выкл».
Субтитры: track внутри <video> для «речи»
<track kind="captions" src="ru.vtt"> внутри <video> — субтитры/тифлокомментарий. Практика: урок-видео с ВТТ. Скринридер «прочтёт» текст? — «не» всегда; дайте транскрипт рядом. Не «прячьте» «смысл» только в звуке. Проверка: кнопка CC. Доступность «медиа». Дисциплина «надписей». Осмысленная «речь» в тексте. Практика: kind="descriptions". Уважение к глухоте. Профессиональный «плеер». Гармония «звук+текст».
Группа radio «как» фильтр: имя у каждого пункта
Фильтр-радио (по цене, по дате) — fieldset+legend «Фильтр», каждый radio с label. Практика: сортировка каталога. Скринридер «прочтёт» легенду и опции. Не «заменяйте» radio «внешним» div-стилем «без» семантики. Проверка: стрелки переключают. Доступность «фильтра». Дисциплина «одного» выбора. Осмысленная «опция». Профессиональная «сортировка». Уважение к выбору. Гармония «рядов-filters». Честный «один-ответ».
Валидация «на лету»: aria-live для сообщения под полем
Сообщение об ошибке появляется — aria-live="assertive" на контейнере подсказки. Практика: пароль валидируется при вводе. Скринридер «озвучит» сразу (assertive прерывает). Не «кричите» на «каждый» ввод — polite для нененавязчивого. Проверка: message под полем прочлось. Доступность «мгновенной» обратной связи. Дисциплина «живой» области. Осмысленный «момент» подсказки. Профессиональная форма. Уважение к темпу. Гармония валидации. Честное «сообщение».
Видео-заставка: poster-кадр без «спойлера»
<video poster="cover.jpg"> — первый «кадр» до «плэя». Практика: курс-превью с фирменным «кадром». Скринридер «не» видит poster — нужен текст/транскрипт рядом. Не «прячьте» «смысл» за видео. Проверка: controls + poster комфортно. Доступность «медиа»-заставок. Дисциплина «первого» кадра. Осмысленная «обложка». Профессиональный «тизер». Уважение к «до-клика». Гармония кадров. Честная «история» на постере.
Список «с аудио»: ссылки на треки с длительностью
Плейлист-список: <ul><li><a>Урок 1 — 12 мин</a></li>… — каждая ссылка «не» форма. Практика: подкаст-серия. Скринридер «прочтёт» название и длительность. Не «вставляйте» <audio> в каждый li «без» контролов. Проверка: имя ссылки осмысленно. Доступность «медиа-ряда». Дисциплина «листа» треков. Осмысленная «длина» в имени. Профессиональный «подкаст». Уважение к времени. Гармония списка. Честная «минута».
Аудио-контролы «свои»: кнопка play с aria-live статусом
Кастомный плеер: кнопка play/pause + <div aria-live=polite> «Статус: воспроизведение». Практика: радиоплеер в шапке. Скринридер «озвучит» переход. Не «вешайте» только иконку (меняется фон) — aria-label меняется с состоянием. Проверка: Space — play/pause. Доступность «плеера». Дисциплина «статуса». Осмысленный «текст». Профессиональный «контрол». Уважение к прослушиванию. Гармония «звука».
Длинный контент: видимая «ссылка-якорь» для tabs через id
«Tabs» «через» якоря (без JS): <nav> ссылки #tab1…, <section id="tab1">. Практика: описание/характеристики товара. Скринридер «прочтёт» ссылки; нажатие «едет» по странице. Не «моделируйте» aria-tab без JS-поведения ролей. Проверка: секции «видимы» (не aria-hidden «навсегда»). Доступность «якорных» вкладок. Дисциплина «простого» таба. Осмысленные секции. Профессиональный «компромисс». Уважение к потоку. Гармония секций. Чистая «навигация». Честный «переход».
Заголовок «с» числом «в» series: h2+маленький «порядковый»
«Часть 3» как h2 + подзаголовок — <hgroup> или «обычный» h2 + p. Практика: серия уроков «Часть III: сетка». Скринридер «прочтёт» как «имя» пары. Не «дублируйте» «порядковый» в двух заголовках. Проверка: имя «вкладки» осмысленно. Доступность «серии». Дисциплина «частей». Осмысленный «номер». Профессиональная «нумерация» глав. Уважение к «эпосу». Гармония «порядка». Честная «часть».