Подтвердить что ты не робот

Недопустимый селектор CSS заставляет исключить правило: что такое обоснование?

Я больше ищу ссылки на рассылку списков рассылки и т.д., а не на спекуляцию.

Может ли кто-нибудь помочь мне узнать обоснование приведенных правил обработки ошибок из CSS Specors Level 3 spec.

Пользовательские агенты должны соблюдать правила обработки ошибок синтаксического анализа:

  • недействителен простой селектор, содержащий недопустимый префикс пространства имен
  • недействительный селектор, содержащий недопустимый простой селектор, недопустимый комбинатор или недопустимый токен.
  • недействительна группа селекторов, содержащих недопустимый селектор.

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

У меня было следующее правило:

#menu li.last, #menu li:last-child {
  ...
}

Чтобы компенсировать отсутствие поддержки IE8 в прошлом месяце, я использовал класс и подгонку JavaScript. Однако это не сработало, потому что IE8 соответствует спецификации CSS при обработке ошибок и отбрасывает все правило, потому что оно не распознает один селектор. Это можно устранить, разделив два селектора на отдельные правила.

Почему это желательно? Почему спецификация не позволяет просто отказаться от непризнанного селектора, но сохранить остальную часть правила?

Я хотел бы знать логическое обоснование, поскольку правила в настоящее время кажутся противоречивыми.

4b9b3361

Ответ 1

Почему это желательно? Почему спецификация не позволяет просто отказаться от непризнанного селектора, но сохранить остальную часть правила?

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


Я предоставлю свой длинный ответ ссылкой другим моим ответом на обработку недействительных селекторов. Комментарий к этому ответу прямо указывает на раздел 4.1.7 спецификации CSS2.1, касающийся ошибок в селекторах в наборах правил, в котором упоминается в качестве примера - запятые в селекторах. Я думаю, он суммирует это довольно красиво:

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

В то время как сама запятая по-прежнему означает группировку двух или более селекторов в отношении селекторов, оказывается, что селектор 4 вводит новые функциональные псевдоклассы, которые принимают группы селектора (или списки выбора) в качестве аргументов, например :matches() (он даже меняет :not(), поэтому он принимает список, что делает его похожим на :matches(), тогда как на уровне 3 он принимает только один простой селектор).

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

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

В качестве примера рассмотрим следующее правило, селектор которого действителен на уровне 4, но не на уровне 3, взятом из этого вопроса:

#sectors > div:not(.alpha, .beta, .gamma) {
    color: #808080;
    background-color: #e9e9e9;
    opacity: 0.5;
}

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

#sectors > div:not(.alpha
.beta
.gamma)

Если он просто отбрасывает первый и последний селектор, которые явно недействительны, оставляя второй селектор действительным, следует ли затем применить правило к любым элементам класса beta? Это явно не то, что автор намеревается сделать, поэтому, если браузер делает это, он перейдет в сделать что-то неожиданное для этого макета. Отбрасывая правило с помощью недействительного селектора, макет выглядит немного скромнее, но это упрощённый пример; правила с стилями изменения макета могут вызвать еще большие проблемы при неправильном применении.

Конечно, могут возникать и другие двусмысленности в синтаксическом селекторе, что может привести к следующим ситуациям:

  • Не знаю, где заканчивается сложный селектор
  • Не зная, где заканчивается список селекторов
  • Не зная, где начинается блок объявлений
  • Комбинация приведенного выше

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

В случае, казалось бы, хорошо сформированных селекторов, которые непризнаны, например :last-child в качестве псевдокласса в вашем примере, спецификация не делает различий между непризнанными селекторами и селекторами, которые просто искажены. Оба результата приводят к ошибке синтаксического анализа. В том же разделе, на который вы ссылаетесь:

Недействительность вызвана ошибкой синтаксического анализа, например. непризнанный токен или токен, который не разрешен в текущей точке синтаксического анализа.

И, сделав это утверждение о :last-child, я предполагаю, что браузер способен анализировать один двоеточие, за которым следует произвольный идентификатор в качестве псевдокласса; на самом деле вы не можете предположить, что реализация будет знать, чтобы синтаксический анализ :last-child как псевдокласса правильно или что-то вроде :lang() или :not() с функциональной нотацией, поскольку функциональные псевдоклассы не отображались до CSS2.

Селекторы определяют определенный набор известных псевдоклассов и псевдоэлементов, имена которых, скорее всего, жестко запрограммированы в каждой реализации. Самые наивные парсеры имеют всю нотацию для каждого псевдокласса и псевдоэлемента, включая одиночный/двойной двоеточие (ы), hardcoded (я не удивлюсь, если основные браузеры действительно делают это с помощью :before, :after, :first-letter и :first-line как специальный случай). Итак, что может показаться псевдоклассом для одной реализации, вполне может быть gobbledygook для другого.

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


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

Я должен также упомянуть, что некоторые механизмы компоновки ведут себя по-разному, например, WebKit игнорируют селектора, отличные от WebKit-prefixed, в правиле, применяя свои собственные префиксы, в то время как другие браузеры полностью игнорируют это правило (вы можете найти больше примеров в Stack Overflow; здесь несколько отличается). В каком-то смысле вы можете сказать, что WebKit обходит правило так, как оно есть, хотя оно пытается рационально разделить группы селекторов, разделенных запятыми, несмотря на эти префиксы селекторов.

Я не думаю, что у рабочей группы есть веские причины изменить это поведение. На самом деле, во всяком случае, у них есть веская причина не менять его, а потому, что сайты уже много лет полагаются на это поведение. Раньше у нас были селекторные хаки для фильтрации старых версий IE; сегодня у нас есть префиксы для фильтрации других браузеров. Эти хаки все полагаются на то же поведение некоторых браузеров, которые отбрасывают правила, которые они не распознают, с другими браузерами, применяющими их, если они считают, что они верны, например. распознавая префиксы (или бросая только нераспознанные из них, как это делает WebKit). Сайты могут ломаться в более новых версиях этих браузеров, если это правило должно было измениться, что совершенно не может произойти в такой разнообразной (читаемой: фрагментированной) Web, как наша.

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

   - RESOLVED: Do not adopt MQ-style invalidation for Selectors
               due to Web-compat concerns.

Недействительность в стиле запроса в отношении мультимедиа относится к недопустимым запросам мультимедиа в списке, разделенном запятыми, без нарушения всего правила @media.