Вычисление специфичности селектора CSS для псевдокласса :not()

Я уже знаю, как рассчитать специфичность селектора для CSS (упомянутые в спецификациях a/b/c/d). Однако мне трудно понять, как вычислить его для псевдокласса :not(). См. следующий пример:

input:not([type="text"],[type="password"],.someClass) {...}
input:not(#someId[type="text"]) {...}

Предполагая, что оба они относятся к одному элементу, должны ли эти два быть рассчитаны как (0011) и, следовательно, должны быть упорядочены в соответствии с порядком появления? Или селекторы внутри псевдокласса :not() следует вычислять отдельно, в зависимости от того, какой из них соответствует, в качестве второго шага для определения того, который имеет приоритет над другим?


person tria    schedule 08.04.2013    source источник
comment
Знаете ли вы, что ваш пример не является допустимым синтаксисом CSS?   -  person thgaskell    schedule 08.04.2013
comment
Не могли бы вы объяснить, что в нем не так? not является частью спецификаций CSS3, и многие браузеры поддерживают несколько селекторов в качестве аргумента для него, если это то, на что вы ссылаетесь, как на недействительное.   -  person tria    schedule 08.04.2013
comment
:not(X) может принимать только простые селекторы. Вам придется расширить его, чтобы он выглядел так: input:not([type="text"]), input:not([type="password"]), input:not(.someClass) {...} и input:not(#someId):not([type="text"]) {...}.   -  person thgaskell    schedule 08.04.2013
comment
Правда, по спецификациям только простые селекторы. Но некоторые браузеры поддерживают несколько. Некоторые из них не делают, а некоторые отказались от них позже. Кроме того, вы можете написать то же правило даже с простыми селекторами, такими как этот: input:not([type="text"]):not([type="password"]):not(.someClass) что лучше и работает также. Означает ли это, что он должен рассчитываться как 0031? Как насчет тех, которые поддерживают несколько, как они вычисляют?   -  person tria    schedule 08.04.2013
comment
Как предлагает @thgaskell, если вам нужна помощь по Stackoverflow, рекомендуется предоставить действительный код (в данном случае CSS, соответствующий спецификациям W3C). Приведенный выше код не выполняет проверку.   -  person Matt Coughlin    schedule 26.04.2013
comment
@thgaskell: вместо этого второй селектор должен расширяться до input:not(#someId), input:not([type="text"]) - см. мой ответ, который я только что опубликовал ниже, а также ответ здесь.   -  person BoltClock    schedule 26.04.2013
comment
@BoltClock: я добавил ответ, пытаясь обобщить логическое намерение правил CSS и почему действительный эквивалент CSS имеет такую ​​​​форму. Не могли бы вы просмотреть его, чтобы увидеть, если что-то не так? Спасибо!   -  person Matt Coughlin    schedule 26.04.2013


Ответы (3)


Предполагая, что оба они относятся к одному элементу, должны ли эти два быть рассчитаны как (0011) и, следовательно, должны быть упорядочены в соответствии с порядком появления? Или селекторы внутри псевдокласса :not() следует вычислять отдельно в зависимости от того, какой из них соответствует второму шагу, чтобы определить тот, который имеет приоритет над другим?

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

Если вы расширите их, чтобы они проверялись (следуя инструкциям/примерам, приведенным здесь), то их особенности будут рассчитаны следующим образом:

/* 2 attributes, 1 class, 1 type -> specificity = 0-3-1 */
input:not([type="text"]):not([type="password"]):not(.someClass)

/* 
 * 1 ID, 1 type        -> specificity = 1-0-1
 * 1 attribute, 1 type -> specificity = 0-1-1
 */
input:not(#someId), input:not([type="text"])

Потому что Selectors 3 говорит:

Селекторы внутри псевдокласса отрицания учитываются как любые другие, но само отрицание не считается псевдоклассом.

Также в ответ на ваш комментарий:

Правда, по спецификациям только простые селекторы. Но некоторые браузеры поддерживают несколько. Некоторые из них не делают, а некоторые отказались от них позже. Кроме того, вы можете написать то же правило даже с простыми селекторами, такими как этот: input:not([type="text"]):not([type="password"]):not(.someClass) что лучше и работает также. Означает ли это, что он должен рассчитываться как 0031? Как насчет тех, которые поддерживают несколько, как они вычисляют?

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

Мне непонятно, как Firefox 3.0 реализовал специфичность со своей версией селектора :not(), и у меня нет его копии для тестирования, но я думаю, можно с уверенностью предположить, что это больше не имеет значения, поскольку в любом случае это никогда не было предполагаемым поведением. Хорошо, поэтому я взял Firefox 3.0 beta 1, 3.0.0, 3.0.18 и 3.1 beta 1, и ни одна из них вообще не воспроизводит это поведение. Итак, у вас есть это.


1 Обратите внимание, что и в текущем ED 2013 г., и в FPWD 2011 г. говорится, что специфичность :not() равна специфичности его наиболее конкретного аргумента, но это может измениться в будущем.< /под>

person BoltClock    schedule 26.04.2013
comment
Извините, я совсем забыл об этом вопросе. Отличный ответ. Теперь мне ясно. Отмечено и проголосовано. Большое спасибо за то, что поделились. - person tria; 28.04.2013

Логическое намерение

Ниже приведена разбивка селекторов CSS, изначально опубликованных в вопросе. Это попытка обобщить то, как оба правила CSS могут быть выражены с использованием допустимого CSS (обсуждение, начатое @thgaskell и @BoltClock). Я оставлю вопрос специфики другим авторам.

Первое правило

input:not([type="text"],[type="password"],.someClass) {}

Это непроверяющий селектор в CSS3, который в настоящее время может не поддерживаться ни одним из известных браузеров.

Логическим намерением селектора является !(a or b or c), что эквивалентно !a and !b and !c. Для селекторов CSS логическая операция and требует цепочки, которая может быть выражена как :not(a):not(b):not(c).

Таким образом, первое правило может быть выражено в корректном CSS следующим образом:

input:not([type="text"]):not([type="password"]):not(.someClass) {}

Второе правило

input:not(#someId[type="text"]) {}

Это непроверяющий селектор в CSS3, который в настоящее время может не поддерживаться ни одним из известных браузеров.

Логическое назначение селектора — !(a and b), что эквивалентно !a or !b. Для селекторов CSS логическая операция or требует использования нескольких селекторов (по одному селектору на каждый операнд), что можно выразить как :not(a), :not(b).

Таким образом, второе правило может быть выражено в корректном CSS следующим образом:

input:not(#someId), input:not([type="text"]) {}

Резюме

Логическая операция and требует связывания каждого операнда.

.a.b {}                /* Matches elements with both classes  */
                       /*     (a and b)                       */

:not(.a):not(.b) {}    /* Matches elements with neither class */
                       /*     (!a and !b) == !(a or b)        */

Логическая операция or требует использования нескольких селекторов (по одному селектору на каждый операнд).

.a, .b {}              /* Matches elements with either class              */
                       /*     (a or b)                                    */

:not(.a), :not(.b) {}  /* Matches elements that don't have both classes   */
                       /* (elements with none or only one of the classes) */
                       /* (aka: not both, nand, alternative denial        */
                       /*     (!a or !b) == !(a and b)                    */
person Matt Coughlin    schedule 26.04.2013

В спецификации (W3C Selectors Level 3) довольно четко указано, что псевдоклассы считаются как классы.

Некоторые эксперименты с jsfiddle в основных браузерах указывают на то, что вы правы (в своем комментарии), и специфика для

 input:not([type="text"]):not([type="password"]):not(.someClass) {border:3px solid red}

... будет 0.0.3.1. Требуется 3 имени класса в объявлении стиля, которое появится позже, чтобы переопределить вышеуказанный селектор.

Данный:

<input value="X" class="Y Z" id="myId"/>

Вы не можете переопределить вышеуказанный селектор только:

input.Y.Z{border:3px solid pink;}

См. http://jsfiddle.net/mhfaust/SxavM/1/.

обновление BoltClock прав. В спецификации указано, что «селекторы внутри псевдокласса отрицания учитываются, как и любые другие, но само отрицание не считается псевдоклассом». Таким образом, поскольку каждый селектор внутри :not() в этом примере является именем класса или псевдоклассом, специфичность остается равной 0.0.3.1.

person Faust    schedule 26.04.2013
comment
В спецификации также довольно четко указано, что :not() считается по-другому. Совершенно случайно, что используемые здесь селекторы являются селекторами атрибутов, которые также весят так же, как селекторы классов и псевдоклассы. - person BoltClock; 26.04.2013