Почему это объявление 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>

Два вопроса:

  1. Почему мой CSS применяется как к да 1, так и к 2?
  2. Почему все это ломается, если я переключаюсь на универсальный селектор?

    *:not(.no) span{background-color:#00f;}
    

Вот код в JSFiddle: http://jsfiddle.net/stephaniehobson/JtNZm/

3 ответа

Решение
  1. Оба из span родительский элемент 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>
    
  2. И то и другое html а также bodyпредки твои div а также span элементы, удовлетворяющие *:not(.no) при использовании универсального селектора (точнее, при пропуске селектора типа). Это вызывает все ваши span элементы, чтобы иметь цвет фона.

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

body > div:not(.no) span { background-color: #00f; }

jsFiddle demo

Другое решение - просто использовать стили переопределения.

BoltClock это правильно. Это может иметь больше смысла, если вы сформулируете селектор следующим образом:

Выберите любой span элемент
что происходит от div элемент
чья class значение не содержит слова no,

Каждый из выбранных span S в вашем примере на самом деле происходит от div чья class значение не содержит слова no - тот факт, что второй из них также произошел от div чья class значение содержит слово no не отменяет (ха!) предыдущее утверждение.

Что интересно, я бы держал пари, что если вы переместили второй no вниз уровень, второй span все равно будет соответствовать. У CSS нет понятия близости элементов, поэтому любой предок div должно быть достаточно для выбора селектора, независимо от того, находится ли он "ближе" к span или нет.

Я думаю, что лучший выбор - разделить ваше заявление на 2:

div span { background-color:#00f; }
.no span { background-color:#fff; }

Вы можете увидеть эффект здесь: http://jsfiddle.net/JHTqp/

Другие вопросы по тегам