Почему этот фильтр CSS: not() не фильтруется?
Я хочу выбрать промежутки, которые не являются потомками определенного класса, и назовите его "нет". Здесь мой CSS:
div:not(.no) span{background-color:#00f;}
Здесь HTML
<div>
<span>yes 1</span>
</div>
<div class="no">
<span>no 1</span>
</div>
<div class="no">
<div>
<span>no 2</span>
</div>
</div>
Два вопроса:
- Почему мой CSS применим как к yes 1, так и к no 2?
-
Почему все это ломается, если я переключаюсь на универсальный селектор?
*:not(.no) span{background-color:#00f;}
Здесь код в JSFiddle: http://jsfiddle.net/stephaniehobson/JtNZm/
Ответы
Ответ 1
-
Оба элемента span
элементов div
элементов класса div
не имеют класса no
, независимо от того, есть ли у него какие-либо другие предки:
<div> <!-- This is div:not(.no), pretty much a given -->
<span>yes 1</span>
</div>
<div class="no"> <!-- In this case, although this is div.no... -->
<div> <!-- ... this is div:not(.no)! -->
<span>no 2</span>
</div>
</div>
-
Оба html
и body
, которые являются предками ваших элементов div
и span
, удовлетворяют *:not(.no)
при использовании универсального селектора (точнее, при отсутствии селектора типов). Это приведет к тому, что все ваши элементы span
будут иметь цвет фона.
Одним из решений этого является привязка фильтра отрицания к элементу body
с использованием детского комбинатора, если элементы верхнего уровня div
всегда будут дочерними элементами body
:
body > div:not(.no) span { background-color: #00f; }
jsFiddle demo
Другое решение - просто использовать стили переопределения.
Ответ 2
BoltClock является правильным. Это может иметь смысл, если вы произнесете селектор следующим образом:
Выберите любой элемент span
который происходит от элемента div
значение class
не содержит слова no
.
Каждый из выбранных span
в вашем примере на самом деле происходит от div
, значение class
которого не содержит слова no
- тот факт, что второе из них также происходит от a div
, значение class
которого содержит слово no
, не отменяет (ha!) предыдущее утверждение.
Интересно, что я бы сказал, что если вы переместили второй no
вниз на уровень, второй span
по-прежнему будет соответствовать. CSS не имеет понятия близости к элементу, поэтому любому предшественнику div
должно быть достаточно, чтобы соответствовать селектору, независимо от того, "ближе ли он" к span
или нет.
Ответ 3
Я думаю, что лучший выбор - разделить ваше утверждение на 2:
div span { background-color:#00f; }
.no span { background-color:#fff; }
Вы можете увидеть эффект здесь: http://jsfiddle.net/JHTqp/