2012-05-23 139 views
53

我有这样的布局:为什么我的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到unassigned类添加到不返回其他类的一个alphabeta或部门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

为什么jQuery中的:not()选择工作,但是在CSS中失败?它不应该在两个地方同样的工作,因为jQuery声称是“CSS3兼容”,或者有什么我失踪?

有没有一个纯粹的CSS解决方法,或者我将不得不依靠一个脚本?

+1

相关:[组合:不是()选择器在CSS](http://stackoverflow.com/questions/7403129/combining-not-selectors-in-css) – BoltClock

+0

也相关:[百科全书堆栈交换](http ://blog.stackoverflow.com/2012/05/encyclopedia-stack-exchange) - 这是我对它的第一个实验,到目前为止,除了那个流氓downvote,我必须说它比我预期的更好: ) – BoltClock

回答

68

为什么: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
  • 类型选择器(adivspanulli等)任选地,用namespace
  • 属性选择器([att][att=val]等),任选地具有namespace
  • 类选择(.class
  • ID选择器(#id
  • 伪类(:pseudo-class

因此,这里有jQuery's :not() selectorthe 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

  2. 你不能简单的选择组合成复合选择使用与: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) 
    

    由于你可以看到,这比第一点更不方便。

  3. 你不能使用组合器。这个工作在jQuery的,但不是CSS:

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

    这是一个特别讨厌的情况下,主要是因为它没有适当的解决方法。有一些宽松变通办法(12),但它们几乎总是依赖于HTML结构,因此非常有用的实用程序。

  4. 在实现querySelectorAll()浏览器和:not()选择,在一定程度上使得它选择字符串中使用:not()有效的CSS选择器将导致该方法直接返回,而不是回落到嘶嘶声(jQuery的选择结果,引擎实现了:not()扩展)。如果你是一个表现坚定的人,这是一个绝对让你垂涎的微不足道的奖励。

好消息是,Selectors 4 enhances the :not() selector允许用逗号分隔的复杂选择器列表。一个复杂的选择器就是一个简单的或复合选择器,或者是由组合器分隔的整个复合选择器链。总之,你在上面看到的一切。

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


虽然this article说,你可以在Firefox 3传递一个逗号分隔的选择列表来:not(),你不应该要能。如果它在Firefox 3中正如该文章所声称的那样工作,那么这是因为Firefox 3中的一个错误,我无法再找到该错误消息,但在未来的浏览器实施未来的标准之前它不应该起作用。看到这篇文章被引用到目前为止的频率,我已经离开了comment这个效果,但也看到文章的年代和网站更新频率很少,我真的不指望作者回来修复它。

+3

那篇文章真的很烦人。这似乎是人们认为':not(#foo,#foo *)'在CSS中工作的唯一原因。那么,支持它的jQuery也可能与它有关。 – thirtydot

+0

到目前为止仅支持Safari 4级选择器,http://caniuse.com/#search=%3Anot – Carlos

相关问题