为啥我的 jQuery :not() 选择器在 CSS 中不起作用?
Posted
技术标签:
【中文标题】为啥我的 jQuery :not() 选择器在 CSS 中不起作用?【英文标题】:Why is my jQuery :not() selector not working in CSS?为什么我的 jQuery :not() 选择器在 CSS 中不起作用? 【发布时间】:2012-05-29 12:23:51 【问题描述】:我有这个布局:
<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;
在现代浏览器中一切都可以完美运行。
Interactive jsFiddle preview
但是看到:not()
selector in jQuery 基于:not()
in CSS3,我想我可以将它直接移动到我的样式表中,这样我就不必依赖使用jQuery 添加额外的类。此外,我对支持旧版本的 IE 并不感兴趣,其他浏览器对 :not()
选择器的支持非常好。
所以我尝试将上面的.unassigned
部分更改为这个(知道我的布局中只有扇区 Α、Β 和 Γ):
#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;
但一旦我这样做,它就会停止工作——在所有浏览器中!我的未分配扇区不再变灰、淡出或标记为“未分配”。
Updated but not so interactive jsFiddle preview
为什么:not()
选择器在 jQuery 中有效,但在 CSS 中失败?既然 jQuery 声称“符合 CSS3 标准”,那么它在这两个地方的工作方式是否应该相同,还是我遗漏了什么?
是否有纯 CSS 解决方法或者我必须依赖脚本?
【问题讨论】:
相关:Combining :not() selectors in CSS 也相关:Encyclopedia Stack Exchange - 这是我第一次尝试它,到目前为止,除了那个流氓反对票之外,我必须说它比我预期的要好:) 【参考方案1】:为什么
:not()
选择器在 jQuery 中有效,但在 CSS 中失败?既然 jQuery 声称“符合 CSS3 标准”,那么它在这两个地方的工作方式是否应该相同,还是我遗漏了什么?
也许它应该,但事实证明它不:jQuery 扩展了:not()
选择器使得you can pass any selector to it,不管它可能多么复杂是,并且我怀疑这样做的主要原因是为了与.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 preview
请记住,将逗号分隔的选择器列表传递给:not()
意味着过滤不匹配任何列出的选择器的元素。
另一方面,现在:not()
pseudo-class in Selectors level 3 本身非常有限。您只能将一个简单的选择器作为参数传递给:not()
。这意味着您一次只能通过其中任何一项:
*
),可选择使用 namespace
类型选择器(a
、div
、span
、ul
、li
等),可选择使用namespace
属性选择器([att]
、[att=val]
等),可选择使用namespace
类选择器 (.class
)
ID 选择器 (#id
)
伪类 (:pseudo-class
)
所以,这里是jQuery's :not()
selector 和the current standard's :not()
selector 之间的区别:
首先,直接回答这个问题:你不能传递逗号分隔的选择器列表。1例如,虽然给定的选择器在 jQuery 中工作如小提琴所示,它不是有效的 CSS:
/* If it's not in the Α, Β or Γ sectors, it's unassigned */
#sectors > div:not(.alpha, .beta, .gamma)
是否有纯 CSS 解决方法或者我必须依赖脚本?
谢天谢地,在这种情况下,有。您只需一个接一个地链接多个 :not()
选择器,以使其成为有效的 CSS:
#sectors > div:not(.alpha):not(.beta):not(.gamma)
它不会使选择器 更长,但不一致和不便仍然很明显。
Updated interactive jsFiddle preview
您不能将简单选择器组合成复合选择器以用于:not()
。这在 jQuery 中有效,但 CSS 无效:
/* Do not find divs that have all three classes together */
#foo > div:not(.foo.bar.baz)
您需要将其拆分为多个否定(不仅仅是链接它们!)以使其成为有效的 CSS:
#foo > div:not(.foo), #foo > div:not(.bar), #foo > div:not(.baz)
如您所见,这比第 1 点更不方便。
你不能使用组合器。这适用于 jQuery,但不适用于 CSS:
/*
* Grab everything that is neither #foo itself nor within #foo.
* Notice the descendant combinator (the space) between #foo and *.
*/
:not(#foo, #foo *)
这是一个特别糟糕的情况,主要是因为它没有适当的解决方法。有一些松散的变通方法(1 和2),但它们几乎总是依赖于 html 结构,因此实用性非常有限。
在实现querySelectorAll()
和:not()
选择器的浏览器中,在选择器字符串中使用:not()
使其成为有效的CSS 选择器将导致方法直接返回结果,而不是回到 Sizzle(jQuery 的选择器引擎,它实现了 :not()
扩展)。如果你是一个追求表现的人,这绝对是一笔微不足道的奖励,你肯定会垂涎三尺。
好消息是Selectors 4 enhances the :not()
selector 允许使用逗号分隔的复杂选择器列表。一个复杂的选择器要么是一个单独的简单或复合选择器,要么是由组合器分隔的整个复合选择器链。简而言之,就是您在上面看到的所有内容。
这意味着上面的 jQuery 示例将成为有效的 4 级选择器,这将使伪类在未来几年 CSS 实现开始支持它时变得更加有用。
1虽然this article 说您可以在Firefox 3 中将逗号分隔的选择器列表传递给:not()
,但您不应该这样做。如果它像那篇文章声称的那样在 Firefox 3 中工作,那是因为 Firefox 3 中的一个错误,我再也找不到票了,但在未来的浏览器实现未来标准之前它不应该工作。看到这篇文章迄今为止被引用的频率,我为此留下了comment,但也看到这篇文章有多旧以及网站更新的频率有多低,我真的不指望作者回来修复它。
【讨论】:
那篇文章真的很烦人。它似乎完全负责人们认为:not(#foo, #foo *)
在 CSS 中工作。嗯,也许支持它的jQuery也与它有关。
目前只有 Safari 支持 4 级选择器,caniuse.com/#search=%3Anot以上是关于为啥我的 jQuery :not() 选择器在 CSS 中不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 jQuery UI 日期选择器在 jQuery 对话框模式中不起作用?
为啥我的 Java 自定义单元格渲染器在选择行/单元格时不显示突出显示?