Перейти к основному содержимому
SiteScan.top

Невалидный HTML: какие ошибки браузер прощает, а какие стоят денег

Дубли id, незакрытые теги, вложенные формы. Ошибки разметки, которые живут, потому что браузер их чинит, и те, что тихо ломают поведение.

HTML · Опубликовано: 8 сентября 2026 г. · 3 мин чтения · Марк Лебедев

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

Ошибки, которые действительно ломают

Дубли id. document.getElementById возвращает первое совпадение и только его. Подпись указывает не на то поле; скрипт вешает обработчик на элемент, по которому никто не кликает. Это самая частая находка на компонентных сайтах: id, зашитый внутри компонента, становится дублем в ту секунду, когда компонент отрисовался дважды.

Вложенные формы. HTML их не допускает, и парсер молча выбрасывает внутреннюю. Кнопка отправки внутри неё перестаёт работать, а код в редакторе выглядит правильным.

Label без цели. for="email" при отсутствии id="email" ломает клик по подписи и лишает поле доступного имени — одна ошибка, которая стоит и удобства, и доступности.

Интерактивные элементы, вложенные друг в друга. Кнопка внутри ссылки или ссылка внутри кнопки дают разное поведение в разных браузерах и непредсказуемый порядок фокуса.

Дублирующиеся атрибуты. <input value="a" value="b"> — второй отбрасывается, и обычно это тот, который кто-то добавил позже, чиня баг.

Ошибки, которые в основном косметические

Незакрытый <li>, одинокий & вместо &amp;, устаревший <center>, отсутствующий type у скрипта. Парсер справляется со всеми, и отрисованная страница идентична. Их стоит чинить, когда это дёшево, но спринта они не заслуживают.

Одна оговорка: незакрытые теги в таблицах и списках меняют форму DOM-дерева, а не только текст разметки, — то есть двигают контент на странице. Такие считайте настоящими.

Почему линтера исходников недостаточно

Шаблоны собираются в рантайме. Компонент, валидный сам по себе, становится невалидным на странице, где он выведен дважды или обёрнут в уже открытую форму. Линтер читает файлы; браузер видит собранный документ. Единственная надёжная проверка — по отрендеренному HTML реальных страниц:

для каждой обойдённой страницы:
  разобрать отданный HTML
  есть ли id, встречающиеся больше раза?
  есть ли формы внутри форм?
  есть ли label[for] без соответствующего id?
  есть ли интерактивные элементы внутри интерактивных?

Запускайте по всему сайту и группируйте по шаблонам — как и с большинством проблем разметки, один плохой компонент объясняет сотню плохих страниц.

Чего стоит пропустить это

Ничего драматичного — в этом и беда. Форма, которая не отправляется на одном шаблоне. Скринридер, называющий не то поле. Обработчик, повешенный на невидимый дубль. Каждое выглядит отдельным багом, получает задачу, получает костыль — а настоящая причина, три строки разметки, остаётся на месте и готовит следующий «отдельный баг».

Читайте также

Проверьте, что из этого есть на вашем сайте

Бесплатное сканирование покажет битые ссылки, ошибки JS и проблемы производительности за минуту.