EverProduct
Фронтенд

Этап 01 · Между кодом и экраном

Подписанные коробки: HTML — это смысл, а не внешний вид

Каждый выбранный тег — подпись, которую прочитают машины: браузер, скринридер, поисковый робот и ты сам через год. «Выглядит одинаково» — самая дорогая фраза во фронтенде.

Две страницы. На экране они совпадают пиксель в пиксель: тот же заголовок, то же меню, те же три карточки, та же кнопка.

Первая собрана из div и span с классами вроде title, menu, card, btn. Вторая — из h1, nav, article, button.

Открой обе — не отличишь. А теперь начни ими пользоваться. На второй Tab проходит по интерактивным элементам, а Enter нажимает кнопку. На первой Tab не делает ничего: div не получает фокус, и человек с клавиатуры до кнопки просто не доберётся. Скринридер объявляет вторую как «кнопка, Отправить»; на первой он не говорит ничего, потому что говорить нечего. Поисковик читает вторую и находит заголовок и статью; в первой он находит стену безымянных коробок.

Пиксели были одинаковые. Всё под ними — разное.

Что значит «семантика»

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

Элемент выбирают так же, как подписывают коробки при переезде. Напиши «вещи» на всех сорока — они по-прежнему хранят ровно то же, что хранили, ты просто уничтожил информацию о содержимом, и расплатится тот, кто будет разгружать машину. div — это коробка с подписью «вещи».

А читателей больше, чем кажется:

  • Браузер, который выдаёт элементам встроенное поведение исходя из того, что они такое.
  • Скринридеры и прочие вспомогательные технологии, которые ходят по структуре: к следующему заголовку, списком всех ссылок, к главной области.
  • Поисковики, которые по структуре взвешивают и пересказывают.
  • Режимы чтения, превью при отправке ссылки, переводчики, автозаполнение браузера — все они гадают по твоей разметке.
  • Тот, кто откроет этот файл через год, включая тебя, и будет читать сотню строк, чтобы понять, где на странице начинается содержимое.

div — это коробка с подписью «вещи». Она работает, а платят все, кто дальше по цепочке.

Поведение, которое ты выбрасываешь

Самый конкретный аргумент — то, что настоящий элемент отдаёт бесплатно.

button получает фокус с клавиатуры, срабатывает и на Enter, и на пробел, объявляется как кнопка со своей подписью, умеет быть отключённым и отправляет форму, если стоит внутри неё. Чтобы кликабельный div с ним сравнялся, нужны tabindex, обработчик клика, обработчик клавиш с отдельными случаями для двух кнопок, ARIA-роль, ARIA-состояние отключённости — и ты всё равно где-нибудь ошибёшься.

Ссылку a с href можно открыть в новой вкладке, скопировать, положить в закладки, перетащить, увидеть в статусной строке и прочитать роботом. div с обработчиком клика, меняющим адрес, — это ссылка, которая работает только у тех, кто пользуется ею ровно так, как ты вообразил.

Правило обобщается. input type="email" приносит клавиатуру с собакой, автозаполнение и бесплатную проверку. input type="date" приносит календарь, сделанный людьми, которые профессионально думали про часовые пояса. details и summary дают аккордеон вообще без JavaScript. dialog даёт модалку с удержанием фокуса и обработкой Escape.

Каждый из этих случаев — поведение, которое кто-то уже написал, проверил на краевых случаях, о которых ты не подумал, и выпустил во всех браузерах. Выбрать безымянную коробку — значит вызваться переписать всё это хуже.

Заголовки — это оглавление

Из всего в этой статье чаще всего портят именно это: заголовки — не размеры шрифта. Это оглавление документа, и вспомогательные технологии ходят по нему так же, как ты ходишь по книге через содержание.

Почти всё покрывается тремя правилами. Один h1 на страницу, называющий, что это за страница. Уровни идут вниз без пропусков: h3 живёт внутри h2, а не сразу под h1 — потому что помельче красивее. И ничто не становится заголовком оттого, что оно жирное и крупное, и не перестаёт им быть оттого, что оформлено мелко.

Если твой h2 визуально слишком большой — меняй CSS. Выбрать h4 ради нужного кегля — ровно та ошибка, ради которой написана эта статья: ты сказал неправду про структуру, чтобы получить размер шрифта.

Ориентиры: форма страницы

Над заголовками лежит слой, описывающий области страницы: header, nav, main, footer, aside, article, section.

Именно они позволяют пользователю прыгнуть сразу к содержимому, а не протабливать сорок пунктов меню на каждой странице, — то же, что ссылка «перейти к содержанию», только автоматически. Один main на страницу. nav — для настоящих навигационных блоков, а не для любой группы ссылок. article — для того, что осмысленно и вынутым по отдельности: пост, комментарий, карточка товара. section — только когда у него есть заголовок; иначе это div, и это нормально.

Что стоит сказать прямо: div и span не запрещены. Это правильный выбор, когда единственная причина существования элемента — раскладка или оформление: обёртка сетки, флекс-строка, кусок текста, который нужно покрасить. Неправильны они только тогда, когда осмысленный элемент существовал, а ты прошёл мимо.

Атрибуты — половина смысла

Половина семантики живёт в атрибутах, и их пропускают ещё чаще, чем элементы.

alt у картинки говорит, что картинка сообщает, — не «изображение графика», а то, что на графике видно. Если картинка чисто декоративная, пустой alt — правильный ответ: он велит вспомогательным технологиям её пропустить. А вот отсутствие атрибута вовсе означает, что вслух прочитают имя файла.

label, связанная с полем через for, — то, что делает подпись кликабельной и то, что заставляет скринридер произнести вопрос, когда фокус попал в поле. Плейсхолдер подписью не является: он исчезает ровно в тот момент, когда человек начал печатать и сильнее всего нуждается в напоминании, чего от него хотели.

lang у элемента html сообщает скринридеру, каким языком произносить, и неверный или отсутствующий lang заставляет читать русский текст английским голосом — то есть неразборчиво. type у полей решает, какую клавиатуру получит человек на телефоне. title в шапке — это вкладка браузера, закладка и строка в выдаче.

Браузер тихо «починит»

Ещё одна вещь, которая потом экономит часы недоумения. HTML намеренно снисходителен: незакрытый тег, ячейка таблицы вне строки, div внутри p — парсер не откажется, он отремонтирует. И ремонт не всегда совпадает с твоим замыслом.

Поэтому то, что ты видишь в инструментах разработчика, иногда не совпадает с тем, что ты написал: ты смотришь на DOM, построенный браузером, а не на свой файл. Когда разметка ведёт себя необъяснимо, сравнение файла с реальным деревом часто и есть весь диагноз.

На практике

Выучи тридцать элементов как следует, а не сотню поверхностно. Заголовки, абзац, списки, ссылки, картинки, семейство форм, таблица и ориентиры. Глубина по этим тридцати стоит больше, чем узнавание сотни, — а узнавание и есть та самая иллюзия, о которой предупреждает сфера «Как учиться»: пролистать справочник ощущается как учёба и не тренирует ничего, кроме ощущения.

Сначала размечай на бумаге. Возьми скриншот любой страницы и до всякого кода напиши, какой элемент должен стоять в каждой области. Две минуты — и решения, которые иначе приняты случайно, приходится принять осознанно.

Выключи CSS. В инструментах разработчика отключи стили и прочитай страницу голой. Если раздетый документ по-прежнему понятен и идёт в правильном порядке — структура верная. Если он превращается в кашу, твой смысл жил в CSS, где машины его не видят.

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

Читай дерево доступности. В инструментах разработчика есть панель, показывающая страницу так, как её видит вспомогательная технология. Это самая быстрая обратная связь, какая существует для этого навыка: абстрактное правило превращается в проверку за десять секунд.

Спрашивай «что это такое?» раньше, чем «как это должно выглядеть?». Каждый раз. Этот вопрос, заданный последовательно в течение месяца, и есть вся привычка.

Проверь себя

Закрой статью и ответь своими словами:

  1. Назови четырёх потребителей твоей разметки помимо отрисовки в браузере.
  2. Что именно даёт button, чего не даёт кликабельный div?
  3. Почему выбор уровня заголовка по размеру шрифта — настоящая ошибка, а не вопрос вкуса?
  4. Когда div — правильный выбор?
  5. В чём разница между пустым alt и отсутствующим alt?
  6. Почему плейсхолдер не заменяет подпись поля?
  7. Почему дерево в инструментах разработчика может отличаться от написанного тобой HTML?

Коротко

  • Две страницы могут выглядеть одинаково и вести себя совершенно по-разному: разметка — это смысл, а смысл читают все, кто дальше по цепочке.
  • Теги называют роли, а не внешний вид, и читатели — браузер, вспомогательные технологии, поисковики, режимы чтения, автозаполнение и ты через год.
  • Настоящие элементы приносят бесплатное поведение: фокус, клавиатура, проверка, календари, диалоги. Воспроизвести это на div — значит переписать хуже.
  • Заголовки — оглавление: один h1, без пропусков уровней, размер решается в CSS.
  • Ориентиры позволяют прыгнуть к содержимому вместо того, чтобы каждый раз протабливать меню.
  • div и span уместны, когда причина — раскладка, и неуместны, когда существовал осмысленный элемент.
  • Половину смысла несут атрибуты: alt, label с for, lang, type у полей.
  • Парсер молча чинит битую разметку, поэтому DOM, который ты изучаешь, может не совпадать с файлом, который ты написал.