Как CSS обрабатывает ошибки

CSS изначально был создан очень снисходительным к ошибкам. Когда браузер натыкается на нечто непонятное в CSS-файле, он испытывает минимальное "удивление", а затем продолжает как ни в чем ни бывало.

Для этого есть важная причина. Мы знаем, что CSS будет расширяться со временем, к нему будут добавляться новые свойства, новые значения и другие новинки. "Новые" вещи выглядят в точности как "невалидные" для старых браузеров, так что, если вам нужно, чтобы язык аккуратно обрабатывал новинки, вам придется оснастить его "умной" обработкой ошибок.

Однако, интересовались ли вы хоть раз, как именно работает обработка ошибок в CSS? Это на самом деле просто. Разбирая таблицу CSS-стилей, браузер в любой момент времени пытается построить либо @-правило, либо стилевое правило, либо объявление (свойство) внутри одного из первых двух.

Если браузер пытается разобрать объявление (свойство) и встречает что-то непонятное, он отбрасывает всё объявление целиком, затем "проматывает" документ вперед, пока не найдет точку с запятой, находящуюся не внутри блока {}, [] или ().

Если браузер пытается разобрать стилевое правило и натыкается на что-то странное, он отбрасывает всё правило, затем "проматывает" вперед, пока не найдет законченный блок {}.

Если браузер пытается разобрать @-правило и встречает что-то странное, он делает и то, и другое — отбрасывает всё @-правило, затем "проматывает" вперед, пока не найдет либо целый блок {}, либо точку с запятой, не лежащую в блоке {}, [] или () (поскольку @-правила встречаются как в виде блоков, типа @media, так и в однострочном виде, типа @import).

Это защищающее от ошибок поведение игнорирует фрагмент таблицы стилей, достаточно маленький для того, чтобы не позволить одной ошибке (или новой функции) разрушить в хлам отображение всей страницы, но достаточно большой для того, чтобы поведение было предсказуемым и дружественным.

Могло ли быть иначе?

Например, предположим, что мы изменили поведение, что оно стало игнорировать меньший фрагмент таблицы стилей — если ошибка внутри функции, оно игнорирует лишь эту функцию. Тогда код вроде этого:

.foo {
  color: white;
  background: black;
  background: radial-gradient(black, rgba(0,0,0,.5)) transparent;
}

…не будет больше правильно работать в браузерах, не понимающих функции radial-gradient(). Он будет создавать лишь прозрачный фон. Нынешнее поведение гарантирует, что "отвалится" всё объявление целиком, так что предыдущий background:black останется в строю вместо него.

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

Перевод статьи "How CSS Handles Errors" с сайта www.xanthir.com, автор Tab Atkins Jr.

P.S. Это тоже может быть интересно:

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.