为什么我的jQuery:not()选择器在CSS中不起作用?

我有这样的布局:

<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将:not()类添加到没有其他类alphabetagamma的扇区中:

$('#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预览

但是看到jQuery中的:not()选择器是基于CSS3中的:not(),我当时想我可以将其直接移到样式表中,这样就不必依靠使用jQuery添加额外的类了。 此外,我对支持IE的较旧版本并不感兴趣,其他浏览器也对:not()选择器提供了出色的支持。

因此,我尝试将上面的:not()部分更改为此(知道我的布局中将只有扇区Α,Β和Γ):

#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;
}

但是,一旦我这样做,它就会停止工作-在所有浏览器中! 我未分配的扇区不再变灰,消失或标记为“未分配”。

更新,但不是交互式的jsFiddle预览

为什么:not()选择器在jQuery中起作用但在CSS中失败? 自从jQuery声称自己是“符合CSS3标准”以来,它在两个地方都不能完全一样工作吗?还是我缺少某些东西?

是否有一个纯CSS解决方法,还是我必须依靠脚本?

1个解决方案
79 votes

为什么#sectors > div:not(.alpha):not(.beta):not(.gamma) 选择器在jQuery中有效,但在CSS中却失败? 自从jQuery声称自己是“符合CSS3标准”以来,它在两个地方都不能完全一样工作吗?还是我缺少某些东西?

也许应该,但是事实并非如此:jQuery扩展了#sectors > div:not(.alpha):not(.beta):not(.gamma) 选择器,无论您多么复杂,您都可以将任何选择器传递给它,而且我怀疑这样做的主要原因是为了与 #sectors > div:not(.alpha):not(.beta):not(.gamma) 方法,该方法还采用任何任意复杂的选择器并进行相应的过滤。 它确实保持了类似于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预览

请记住,将以逗号分隔的选择器列表传递给#sectors > div:not(.alpha):not(.beta):not(.gamma) 意味着筛选与所列的任何选择器都不匹配的元素。

另一方面,现在选择器级别3的#sectors > div:not(.alpha):not(.beta):not(.gamma) 伪类受其自身限制。 您只能将单个简单选择器作为参数传递给#sectors > div:not(.alpha):not(.beta):not(.gamma) 。这意味着您一次只能传递以下任意一个:

  • 通用选择器(#sectors > div:not(.alpha):not(.beta):not(.gamma) ),可选包含名称空间
  • 类型选择器(#sectors > div:not(.alpha):not(.beta):not(.gamma) [att=val]spanulli等),可选带名称空间
  • 属性选择器(#sectors > div:not(.alpha):not(.beta):not(.gamma) [att=val]等),可以选择使用名称空间
  • 类选择器(#sectors > div:not(.alpha):not(.beta):not(.gamma)
  • ID选择器(#sectors > div:not(.alpha):not(.beta):not(.gamma)
  • 伪类(#sectors > div:not(.alpha):not(.beta):not(.gamma)

因此,这是jQuery的#sectors > div:not(.alpha):not(.beta):not(.gamma) 选择器和当前标准的#sectors > div:not(.alpha):not(.beta):not(.gamma) 选择器之间的区别:

  1. 首先,首先要直接回答这个问题:您不能传递以逗号分隔的选择器列表。1例如,虽然给定的选择器在jQuery中工作,如小提琴中所示,但它不是有效的CSS:

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

    是否有一个纯CSS解决方法,还是我必须依靠脚本?

    幸运的是,在这种情况下,确实存在。 您只需要一个接一个地链接多个#sectors > div:not(.alpha):not(.beta):not(.gamma) 选择器,即可使其有效的CSS:

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

    它不会使选择器变长,但是仍然存在明显的不一致和不便之处。

    更新了交互式jsFiddle预览

  2. 您不能将简单的选择器组合到用于:not()的复合选择器中。这在jQuery中有效,但是无效的CSS:

    :not()

    您需要将其拆分为多个取反(不仅仅是链接它们!)以使其有效成为CSS:

    :not()

    如您所见,这比第1点更为不便。

  3. 您不能使用组合器。 这适用于jQuery,但不适用于CSS:

    :not()

    这是一个特别令人讨厌的情况,主要是因为它没有适当的解决方法。 有一些宽松的解决方法(第1和第2种),但是它们几乎始终取决于HTML结构,因此实用性非常有限。

  4. 在实现:not():not()选择器的浏览器中,在选择器字符串中使用:not()以使其成为有效CSS选择器的方式,将导致该方法直接返回结果,而不是退回到Sizzle(jQuery的选择器引擎实现了2603517329090806806787 延期)。 如果您对性能坚持不懈,那肯定是一笔微不足道的奖金,您一定会垂涎三尺。

好消息是,选择器4增强了:not()选择器,允许使用逗号分隔复杂选择器列表。 复杂选择器仅仅是一个简单的简单选择器或复合选择器,或者是由组合器分隔开的整个复合选择器链。 简而言之,您在上方看到的所有内容。

这意味着上面的jQuery示例将成为有效的4级选择器,这将使伪类在未来几年CSS实现开始支持伪类时变得更加有用。


1尽管本文说您可以将用逗号分隔的选择器列表传递给Firefox 3中的:not(),但您不应该能够这样做。 如果该文章声称该功能可在Firefox 3中使用,那是因为Firefox 3中的一个错误我无法再找到该错误的票证,但直到将来的浏览器实现将来的标准时,它才起作用。 看到该文章迄今被引用的频率,我已经对此效果发表了评论,但是还看到了该文章的年代以及该网站的更新频率如何,我真的没有指望作者会回来修复 它。

BoltClock answered 2019-11-07T09:41:01Z
translate from https://stackoverflow.com:/questions/10711730/why-is-my-jquery-not-selector-not-working-in-css