2012-05-23 191 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

相關問題