Вопрос по css3, css, css-selectors, jquery – Почему мой селектор jQuery: not () не работает в CSS?

56

У меня есть этот макет:

<div id="sectors">
    <h1>Sectors</h1>
    <div id="s7-1103" class="alpha"></div>
    <div id="s8-1104" class="alpha"></div>
    <div id="s1-7605" class="beta"></div>
    <div id="s0-7479"></div>
    <div id="s2-6528" class="gamma"></div>
    <div id="s0-4444"></div>
</div>

С этими правилами CSS:

#sectors {
    width: 584px;
    background-color: #ffd;
    margin: 1.5em;
    border: 4px dashed #000;
    padding: 16px;
    overflow: auto;
}

#sectors > h1 {
    font-size: 2em;
    font-weight: bold;
    text-align: center;
}

#sectors > div {
    float: left;
    position: relative;
    width: 180px;
    height: 240px;
    margin: 16px 0 0 16px;
    border-style: solid;
    border-width: 2px;
}

#sectors > div::after {
    display: block;
    position: absolute;
    width: 100%;
    bottom: 0;
    font-weight: bold;
    text-align: center;
    text-transform: capitalize;
    background-color: rgba(255, 255, 255, 0.8);
    border-top: 2px solid;
    content: attr(id) ' - ' attr(class);
}

#sectors > div:nth-of-type(3n+1) {
    margin-left: 0;
}

#sectors > div.alpha { color: #b00; background-color: #ffe0d9; }
#sectors > div.beta  { color: #05b; background-color: #c0edff; }
#sectors > div.gamma { color: #362; background-color: #d4f6c3; }

Я использую JQuery, чтобы добавитьunassigned класс для секторов, которые в противном случае не имеют один из классовalpha, beta или жеgamma:

$('#sectors > div:not(.alpha, .beta, .gamma)').addClass('unassigned');

Затем я применяю некоторые другие правила к этому классу:

#sectors > div.unassigned {
    color: #808080;
    background-color: #e9e9e9;
    opacity: 0.5;
}

#sectors > div.unassigned::after {
    content: attr(id) ' - Unassigned';
}

#sectors > div.unassigned:hover {
    opacity: 1.0;
}

И все работает безупречно в современных браузерах.

Интерактивный предварительный просмотр jsFiddle

Но видя как:not() selector in jQuery основывается на:not() in CSS3Я думал, что смогу переместить его непосредственно в мою таблицу стилей, поэтому мне не придется полагаться на добавление дополнительного класса с использованием jQuery. Кроме того, я не очень заинтересован в поддержке старых версий IE, и другие браузеры имеют отличную поддержку:not() селектор.

Поэтому я пытаюсь изменить.unassigned часть выше к этому (зная, что у меня будут только сектора & # x391 ;, & # x392; и & # x393; в моем макете):

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

#sectors > div:not(.alpha, .beta, .gamma)::after {
    content: attr(id) ' - Unassigned';
}

#sectors > div:not(.alpha, .beta, .gamma):hover {
    opacity: 1.0;
}

Но как только я это делаю, он перестает работать & # x2014; вall browsers! Мои неназначенные сектора не выделены серым цветом, затемнены или не помечены как «неназначенные»; больше.

Обновленный, но не очень интерактивный предварительный просмотр jsFiddle

Почему:not() селектор работает в jQuery, но не работает в CSS? Разве это не должно работать одинаково в обоих местах, поскольку jQuery заявляет, что он «совместим с CSS3», или мне чего-то не хватает?

Есть ли чистый обходной путь CSS для этого, или мне придется полагаться на сценарий?

Также связано:Encyclopedia Stack Exchange - это мой первый эксперимент с ним, и до сих пор, помимо этого мошенничества, я должен сказать, что он оказался лучше, чем я ожидал BoltClock♦
Связанные с:Combining :not() selectors in CSS BoltClock♦

Ваш Ответ

1   ответ
76

:not() selector work in jQuery but fail in CSS? Shouldn't it work identically in both places since jQuery claims to be "CSS3 Compliant", or is there something I'm missing?

Возможно этоshould, но оказывается, что этоdoesn't: jQuery расширяет:not() селектор такой, чтоты можешь пройтиany selector to itкак бы это ни было сложно, иI suspect что главной причиной этого является паритет с.not() method, который также берет любой произвольно сложный селектор и фильтрует соответственно. Он каким-то образом поддерживает CSS-подобный синтаксис, но он выходит за рамки того, что определено в стандарте.

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

/* 
 * Select any section
 * that's neither a child of body with a class
 * nor a child of body having a descendant with a class.
 */
$('section:not(body > [class], body > :has([class]))')

Предварительный просмотр jsFiddle

Помните, что передача списка селекторов через запятую:not() означает фильтрующие элементы, которыеdon't match any of the listed selectors.

Теперь:not() pseudo-class in Selectors level 3С другой стороны, само по себе очень ограничено. Вы можете только пройтиa single simple selector в качестве аргумента:not(), Это означает, что вы можете передать только один из них одновременно:

Universal selector (*), optionally with a namespace Type selector (a, div, span, ul, li, etc), optionally with a namespace Attribute selector ([att], [att=val], etc), optionally with a namespace Class selector (.class) ID selector (#id) Pseudo-class (:pseudo-class)

Итак, вот различия междуJQuery & APOS; s:not() selector а такжетекущий стандарт:not() selector:

First and foremost, to answer the question directly: you can't pass a comma-separated selector list.1 For example, while the given selector works in jQuery as demonstrated in the fiddle, it isn't valid CSS:

/* If it's not in the Α, Β or Γ sectors, it's unassigned */
#sectors > div:not(.alpha, .beta, .gamma)

Is there a pure CSS workaround for this or will I have to rely on a script?

Thankfully, in this case, there is. You simply have to chain multiple :not() selectors, one after another, in order to make it valid CSS:

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

It doesn't make the selector that much longer, but the inconsistency and inconvenience remain evident.

Updated interactive jsFiddle preview

You can't combine simple selectors into compound selectors for use with :not(). This works in jQuery, but is invalid CSS:

/* Do not find divs that have all three classes together */
#foo > div:not(.foo.bar.baz)

You'll need to split it up into multiple negations (not just chain them!) to make it valid CSS:

#foo > div:not(.foo), #foo > div:not(.bar), #foo > div:not(.baz)

As you can see, this is even more inconvenient than point 1.

You can't use combinators. This works in jQuery, but not CSS:

/* 
 * Grab everything that is neither #foo itself nor within #foo.
 * Notice the descendant combinator (the space) between #foo and *.
 */
:not(#foo, #foo *)

This is a particularly nasty case, primarily because it has no proper workaround. There are some loose workarounds (1 and 2), but they almost always depend on the HTML structure and are therefore very limited in utility.

In a browser that implements querySelectorAll() and the :not() selector, using :not() in a selector string in a way that makes it a valid CSS selector will cause the method to return results directly, instead of falling back to Sizzle (jQuery's selector engine which implements the :not() extension). If you're a stickler for performance, this is a positively minuscule bonus you'll definitely salivate over.

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

Это означает, что приведенные выше примеры jQuery станут действительными селекторами уровня 4, что сделает псевдокласс намного, гораздо более полезным, когда реализации CSS начнут его поддерживать в ближайшие годы.

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

Эта статья действительно раздражает. Кажется, что он несет единоличную ответственность за то, что люди думают:not(#foo, #foo *) работает в CSS. Ну, может быть, jQuery, поддерживающий его, тоже как-то связан с этим.
Селекторы уровня 4 пока поддерживаются только в Safari,caniuse.com/#search=%3Anot

Похожие вопросы