58

私はこのレイアウトを持っています:

<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を使用して、他の方法ではクラスの1つunassignedを持たないセクターにクラスを追加します。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プレビュー

しかし:not()、jQueryのセレクターは:not()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;
}

しかし、これを行うとすぐに機能しなくなります—すべてのブラウザで!割り当てられていないセクターは、グレー表示、フェードアウト、または「未割り当て」のラベルが表示されなくなりました。

更新されましたが、それほどインタラクティブではありませんjsFiddleプレビュー

:not()セレクターがjQueryで機能するのに、CSSで失敗するのはなぜですか?jQueryは「CSS3準拠」であると主張しているので、両方の場所で同じように機能するべきではありませんか、それとも私が見逃しているものがありますか?

これに対する純粋なCSSの回避策はありますか、それともスクリプトに依存する必要がありますか?

4

1 に答える 1

83

:not()セレクターがjQueryで機能するのに、CSSで失敗するのはなぜですか?jQueryは「CSS3準拠」であると主張しているので、両方の場所で同じように機能するべきではありませんか、それとも私が見逃しているものがありますか?

おそらくそうすべきですが、そうではないことがわかります:jQueryは:not()セレクターを拡張して、どんなに複雑であっても、セレクター渡すことができるようにします。これの主な理由は、.not()メソッド。これも任意の複雑なセレクターを取り、それに応じてフィルターします。ある意味で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()要素をフィルタリングすることを意味することに注意してください。

一方、セレクターレベル3の:not()疑似クラスは、それ自体で非常に制限されています。への引数として渡すことができるのは、単一の単純なセレクター:not()のみです。これは、一度にこれらのいずれか1つだけを渡すことができることを意味します。

  • ユニバーサルセレクター(*)、オプションで名前空間付き
  • タイプセレクター(、、、、、など) a、オプションでdiv名前空間を使用spanulli
  • 属性セレクター(、、[att]など[att=val])、オプションで名前空間付き
  • クラスセレクター(.class
  • IDセレクター(#id
  • 疑似クラス(:pseudo-class

したがって、 jQueryの:not()セレクター現在の標準の:not()セレクターの違いは次のとおりです。

  1. 何よりもまず、質問に直接答えるには、コンマ区切りのセレクターリストを渡すことはできません。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)
    

    セレクターがそれほど長くなることはありませんが、不整合と不便さは明らかです。

    インタラクティブなjsFiddleプレビューを更新

  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)
    

    ご覧のとおり、これはポイント1よりもさらに不便です。

  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 *)
    

    これは、主に適切な回避策がないため、特に厄介なケースです。いくつかの緩い回避策(1および2)がありますが、それらはほとんどの場合HTML構造に依存しているため、有用性が非常に制限されています。

  4. querySelectorAll()とセレクターを実装するブラウザーで、有効なCSSセレクターになるようにセレクター文字列:not()を使用すると、メソッドはSizzle(拡張機能:not()を実装するjQueryのセレクターエンジン)にフォールバックするのではなく、結果を直接返します。:not()あなたがパフォーマンスにこだわるなら、これはあなたが間違いなく唾を吐くであろうポジティブに微妙なボーナスです。

良いニュースは、セレクター4が:not()セレクターを拡張して、複雑なセレクターのコンマ区切りリストを許可することです。複雑なセレクターは、単純な単一のセレクターまたは複合セレクター、あるいはコンビネーターによって分離された複合セレクターのチェーン全体のいずれかです。要するに、あなたが上で見るすべて。

これは、上記のjQueryの例が有効なレベル4セレクターになることを意味します。これにより、CSS実装が今後数年間で疑似クラスのサポートを開始すると、疑似クラスがはるかに便利になります。


1 この記事では、Firefox 3でセレクターのコンマ区切りリストを渡すことができると述べていますが、渡すことは:not()できないはずです。その記事が主張するようにFirefox3で機能する場合、それはFirefox 3のバグが原因で、チケットを見つけることができませんが、将来のブラウザーが将来の標準を実装するまで機能しないはずです。その記事がこれまでに引用される頻度を見て、この効果についてコメントを残しましたが、記事の古さやサイトの更新頻度も見て、著者が修正に戻ってくることを期待していません。それ。

于 2012-05-23T00:00:59.050 に答える