Spec-Zone.ru › CSS

Обработка ошибок CSS

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

В этом руководстве рассматривается, как CSS парсеры отбрасывают недействительный CSS.

Ошибки парсера CSS

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

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

div {
  display: inline-flex;
  display: inline flex;
}

Свойство display принимает как устаревшее значение с одним параметром, так и синтаксис с несколькими ключевыми словами. Браузеры будут отображать старый синтаксис до тех пор, пока не распознают новый синтаксис как действительный, в этот момент новый синтаксис заменит старый. Если у пользователя старый браузер, действительное значение по умолчанию не будет перезаписано новым CSS, потому что браузер воспринимает его как недействительный.

Тип и количество CSS, которые браузер игнорирует из-за ошибки, зависит от типа ошибки. Ниже перечислены некоторые распространённые ситуации с ошибками:

  • Для ошибок в at-правилах игнорируется вся строка или все at-правило (провал) зависит от at-правила и типа ошибки.
  • Если ошибка — это неверный селектор, весь блок объявления игнорируется.
  • Ошибка из-за отсутствующей точки с запятой между объявлениями свойств приводит к неверному значению, в этом случае игнорируются несколько объявлений свойств-значений.
  • Если ошибка — это имя или значение свойства, например, нераспознанное имя свойства или неверный тип данных, объявление свойства-значения игнорируется.
  • Если ошибка вызвана отсутствием закрывающей скобки, объем игнорируемого содержимого зависит от способности браузера анализировать ошибку как вложенный CSS.

После анализа каждого объявления, правила стиля, at-правила и т. д. браузер проверяет проанализированное содержимое на соответствие ожидаемой грамматике для данного конструктора. Если содержимое не соответствует ожидаемой грамматике данного конструктора, браузер считает его недействительным и игнорирует его.

Ошибки в at-правилах

Символ @, известный в спецификациях CSS как <at-keyword-token>, указывает начало CSS at-rule. После начала at-правила с символа @ ничего не считается недействительным с точки зрения парсера. Всё до первой точки с запятой (;) или открывающей фигурной скобки ({) является частью преамбулы at-правила. Содержимое каждого at-правила интерпретируется в соответствии с правилами грамматики для этого конкретного at-правила.

At-правила для утверждений, такие как @import и @namespace, содержат только преамбулу. Точка с запятой немедленно завершает at-правило для at-правил для утверждений. Если содержимое преамбулы не соответствует грамматике этого at-правила, at-правило игнорируется, и браузер продолжает парсинг CSS после обнаружения следующей точки с запятой. Например, если at-правило @import встречается после любого объявления CSS, кроме @charset, @layer или других @import утверждений, объявление @import игнорируется.

@import "assets/fonts.css" layer(fonts);
@namespace svg url(http://www.w3.org/2000/svg);

Если парсер находит фигурную скобку ({) до точки с запятой, at-правило анализируется как at-правило с блоком. At-правила с блоками, такие как @font-face и @keyframes, содержат блок объявлений, окружённых фигурными скобками ({}). Открывающая фигурная скобка сообщает браузеру, где заканчивается преамбула at-правила и начинается тело at-правила. Парсер смотрит вперёд, ища соответствующие блоки (содержимое, окружённое (), {}, или []). Пока не найдёт закрывающую фигурную скобку (}), которая не соответствует никаким другим фигурным скобкам: это закрывает тело at-правила.

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

Например, правило @font-face требует как описателя font-family, так и src. Если какой-либо из них отсутствует или недействителен, всё правило @font-face считается недействительным. Включение не относящегося к этому описателя, любого другого действительного описателя шрифта с недействительным значением или объявления стиля свойства внутри вложенного блока @font-face не сделает объявление шрифта недействительным. Пока имя и источник шрифта включены и действительны, любой недействительный CSS внутри at-правила игнорируется, но блок @font-face по-прежнему анализируется.

Хотя грамматика at-правила @keyframe сильно отличается от грамматики правила @font-face, тип ошибки по-прежнему влияет на то, что игнорируется. Важные объявления (помеченные флагом important) и свойства, которые нельзя анимировать, игнорируются в правилах ключевых кадров, но они не влияют на другие стили, объявленные в том же блоке селекторов ключевых кадров. Включение недействительного селектора ключевых кадров (например, значение процента меньше 0% или больше 100%, или <number> без %) делает список селекторов ключевых кадров недействительным, и, следовательно, блок стиля игнорируется. Недействительный селектор ключевого кадра делает недействительным только блок стиля этого недействительного селектора; он не делает недействительным всё объявление @keyframe. С другой стороны, включение стилей между двумя блоками селекторов ключевых кадров сделает всё at-правило @keyframe недействительным.

Некоторые at-правила почти всегда действительны. At-правило @layer существует в обычном и вложенном форматах. Синтаксис утверждения @layer содержит только преамбулу, заканчивающуюся точкой с запятой. В качестве альтернативы, вложенный синтаксис имеет вложенные стили слоя между фигурными скобками после преамбулы. Пропуск закрывающей фигурной скобки может быть логической ошибкой, но не синтаксической. В случае отсутствия закрывающей скобки в @layer, все стили, следующие за тем местом, где должна была быть закрывающая скобка, анализируются как находящиеся в каскадном слое, определённом в преамбуле at-правила. CSS действителен, так как синтаксических ошибок нет; ничего не отбрасывается. Синтаксическая ошибка может привести к тому, что именованный или анонимный слой будет пустым, но слой всё равно создаётся.

Ошибки в списках селекторов

Существует множество способов допустить ошибку при написании селектора, но только неверные селекторы делают список селекторов недействительным (см. недействительный список селекторов).

Если вы включили class, id или type селектор для класса, идентификатора или элемента (или пользовательского элемента), которого не существует, это может быть логической ошибкой, но не синтаксической ошибкой. Однако, если у вас есть опечатка в псевдоклассе или псевдоэлементе, это может создать недействительный селектор, который парсер должен обработать как ошибку.

Если список селекторов содержит какие-либо недействительные селекторы, то весь блок стиля игнорируется. Есть исключения: если недействительный селектор находится внутри :is или :where псевдокласса (которые принимают поблажки в списках селекторов) или если неизвестный селектор — это -webkit- префиксный псевдоэлемент, игнорируется только неизвестный селектор как не соответствующий ничему. Список селекторов не считается недействительным.

За исключением этих случаев, один недействительный или неподдерживаемый селектор в списке селекторов сделает всё правило недействительным, и весь блок селектора будет проигнорирован. Затем браузер будет искать закрывающую фигурную скобку и продолжит парсинг с этого места.

Исключение -webkit-

Из-за исторических проблем с чрезмерным использованием браузерных префиксов в селекторах и имен (и значениях) свойств, браузеры избегают чрезмерной проверки списков селекторов, рассматривая все псевдоэлементы, начинающиеся с нечувствительного к регистру префикса -webkit- и не заканчивающиеся на (), как действительные.

Это означает, что псевдоэлемент, такой как ::-webkit-works-only-in-samsung, не сделает список селекторов недействительным независимо от того, в каком браузере выполняется код. В таких случаях псевдоэлемент может не распознаваться или не поддерживаться браузером, но это не приведёт к тому, что весь список селекторов и связанный с ним блок стиля будут проигнорированы. С другой стороны, неизвестный префиксный селектор с функцией записи ::-webkit-imaginary-function() сделает весь список селекторов недействительным, и браузер проигнорирует весь блок селектора.

Ошибки в блоках объявления CSS

Что касается свойств и значений CSS в блоке объявления, если свойство или значение некорректны, эта пара свойство-значение игнорируется и отбрасывается. Когда пользовательский агент анализирует или интерпретирует список объявлений, неизвестный синтаксис в любой точке заставляет анализатор браузера отбросить только текущее объявление. Затем он продолжает анализ CSS после следующей точки с запятой или закрывающей фигурной скобки, что произойдёт раньше.

Этот пример содержит ошибку. Анализатор игнорирует ошибку (и комментарии), ищет вперёд, пока не встретит точку с запятой, а затем возобновляет анализ:

p {
/* Invalid syntax due to  missing semi-colon */
  border-color: red
  background-color: green;

/* Valid syntax but likely a logic error */
  border-width: 100vh;
}

Причина, по которой первое объявление в этом блоке селектора некорректно, заключается в том, что отсутствует точка с запятой, а объявление не является последним в блоке селектора. Свойство, у которого отсутствует точка с запятой, игнорируется, как и пара свойство-значение, следующая за ним, так как браузер возобновляет анализ только после точки с запятой или закрывающей скобки. В частности, значение border-color анализируется как red background-color: green;, что не является допустимым значением <color>.

Значение border-width 100vh, скорее всего, является ошибкой, но это не ошибка. Поскольку оно синтаксически верно, оно будет проанализировано и применено к элементам, соответствующим селектору.

Префиксы поставщиков

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

Вы можете столкнуться с устаревшим CSS, который выглядит следующим образом:

/* Prefixed values */
.wrapper {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  display: block flex;
}
/* Prefixed properties */
.rounded {
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  -ms-border-radius: 50%;
  -o-border-radius: 50%;
  border-radius: 50%;
}

В этом примере последнее объявление в каждом блоке допустимо во всех браузерах — display: flex; и border-radius: 50%;. Из-за правила каскада порядка появления слоёв каскада браузеры применяют все префиксные объявления, которые они понимают, а затем перезаписывают эти значения стандартной версией без префиксов.

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

Ошибки с автоматическим закрытием

Если стиловый лист завершается, когда правило, объявление, функция, строка или комментарий всё ещё открыты, парсер автоматически закроет всё, что осталось незакрытым.

Примечание: Это относится к внешним стиловым листам, блокам селекторов внутри HTML-элемента <style> и встроенным правилам внутри атрибута style.

Если содержимое между последней точкой с запятой и концом стилового листа допустимо, даже если оно неполное, CSS будет проанализирован нормально. Например, если вы не закроете объявление @keyframe перед закрытием вашего <style>, анимация всё равно будет допустимой.

<style>
@keyframes move {
  100% {
    transform: translateX(100vw)
</style>

Здесь анимация move допустима. Неправильное закрытие операторов CSS не обязательно делает операторы недопустимыми. Однако не злоупотребляйте допусками CSS. Всегда закрывайте все ваши операторы и блоки стилей. Это делает ваш CSS легче читать и поддерживать, и гарантирует, что браузер анализирует CSS так, как вы намеревались.

Незакрытые комментарии

Незакрытые комментарии — это ошибки логики, а не синтаксические ошибки. Если комментарий начинается с /*, но не закрывается, весь код CSS до закрывающего разделителя (*/) в последующем комментарии или до конца стилового листа, что произойдет раньше, является частью комментария. Хотя незакрытый комментарий не делает ваш CSS недопустимым, он приводит к тому, что CSS, следующий за открывающим разделителем (/*), игнорируется.

<style>
  /* this comment is not closed
  @keyframes move {
    0% {transform: translateX(0);}
    100% {transform: translateX(100vw);}
  }
</style>
<p style="/* another unclosed comment">Parsed as HTML.</p>

В этом примере два комментария CSS не закрыты, но закрывающая тег </style> закрывает первый комментарий, а закрывающая кавычка атрибута style закрывает второй комментарий.

Проверка грамматики

После анализа каждого объявления, правила стилей, атрибутов и т. п., пользовательский агент проверяет, соответствует ли грамматика правилам для данного объявления. Например, если значение свойства имеет неправильный тип данных или дескриптор не является допустимым для атрибута, описываемого атрибутом, содержимое, которое не соответствует ожидаемой грамматике, считается недопустимым и игнорируется.

Каждое свойство CSS принимает определённые типы данных. Например, свойство background-color принимает либо допустимое значение <color>, либо глобальное ключевое слово CSS. Когда значение, присваиваемое свойству, имеет неправильный тип, например background-color: 45deg, объявление считается недопустимым и, следовательно, игнорируется.

Некорректные пользовательские свойства

Пользовательские свойства, как правило, считаются допустимыми при объявлении, но могут создавать некорректный CSS при обращении, т. е. они могут использоваться в качестве значения (через функцию var()) для свойства, которое не принимает этот тип значения. Браузер анализирует каждое пользовательское свойство при его встрече, не обращая внимания на то, где это свойство используется.

Как правило, когда значение свойства некорректно, объявление игнорируется, и свойство возвращается к последнему допустимому значению. Однако некорректные вычисленные значения пользовательских свойств работают немного иначе.

Когда замена var() некорректна, объявление не игнорируется, а используется начальное или унаследованное значение свойства. Свойство устанавливается в новое значение, но, возможно, не ожидаемое.

Давайте рассмотрим пример, чтобы проиллюстрировать это поведение:

:root {
  --theme-color: 45deg;
}
body {
  background-color: var(--theme-color);
}

В приведенном выше коде объявление пользовательского свойства допустимо. Объявление background-color также допустимо на этапе вычисления. Однако, когда браузер заменяет пользовательское свойство в var(--theme-color) значением 45deg в качестве значения свойства background-color, грамматика становится некорректной. <angle> не является допустимым значением для background-color. В этом случае объявление не игнорируется как некорректное. Скорее, когда пользовательское свойство имеет неправильный тип, если свойство наследуется, значение наследуется от родителя. Если свойство не наследуется, используется значение по умолчанию. В случае background-color значение свойства не является унаследованным значением, поэтому используется начальное значение transparent.

Для лучшего контроля возврата пользовательских свойств используйте атрибут @property, чтобы определить начальное значение свойства:

@property --theme-color {
  syntax: "<color>";
  inherits: false;
  initial-value: rebeccapurple;
}

См. также

  • Модуль синтаксиса CSS
  • Руководство по синтаксису
  • Синтаксис определения значения

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_syntax/Error_handling

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API