Ответ 1
Должен ли он работать так, как я думаю, он должен?
Нет, поведение, которое вы видите, верное.
В вашем последнем примере, хотя <blockquote>
содержит <p>
, он сам <blockquote>
, который соответствует *:not(p)
, а также условие, что он должен быть потомком <div>
, который он является. Стиль применяется только к <blockquote>
, но затем он наследуется <p>
внутри него.
Элемент <p>
по-прежнему считается против отрицания, поэтому сам <p>
по-прежнему исключается из вашего селектора. Он просто наследует цвет текста от его родителя, элемент <blockquote>
.
Даже если ни один из его относительно близких предков не подходил к селектору, вы также должны беспокоиться о таких элементах, как html
и body
, хотя вы могли бы вначале просто нажать на селектор body
:
body div...
Вот почему я часто настоятельно рекомендую использовать селектор :not()
для фильтрации потомков, особенно если он не квалифицирован с помощью селектора типов (например, div
в вашем примере). Это не работает так, как этого ожидают многие люди, а использование унаследованных свойств, таких как color
, служит только для того, чтобы усугубить проблему, в то же время сделать ее еще более запутанной для авторов. См. Мои ответы на эти другие вопросы для получения дополнительных примеров:
- Почему этот фильтр CSS: not() не фильтруется?
- Псевдо-класс CSS negation: not() для элементов parent/ancestor
Решение описанной проблемы - это просто применить другой цвет к элементам <p>
. Вы не сможете просто исключить их с помощью селектора из-за наследования:
/* Apply to div and let all its descendants inherit */
div {
color: red;
}
/* Remove it from div p */
div p {
color: black;
}
On Selectors Level 4: yes, :not()
действительно расширен, чтобы принимать полные сложные селектора, содержащие комбинаторы. По сути, это означает, что (как только браузер начнет ее внедрять), вы сможете написать следующий селектор и выполнить его именно то, что вы хотите:
p:not(div p) {
color: red;
}
В случае, если кто-то заинтересован, это работает сегодня в jQuery.