web-dev-qa-db-ja.com

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

そして、すべてが最新のブラウザで問題なく動作します。

インタラクティブjsFiddleプレビュー

しかし :not()セレクターjQuery:not() in CSS ​​に基づいているので、直接移動できると思っていました私のスタイルシートなので、jQueryを使用して追加のクラスを追加する必要はありません。その上、私は古いバージョンのIEのサポートにはあまり興味がなく、他のブラウザーは:not()セレクターに優れたサポートを提供しています。

したがって、上記の_.unassigned_の部分をこれに変更してみます(レイアウトにはセクターΑ、Β、およびonlyしかありません)。

_#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の回避策はありますか、それともスクリプトに依存する必要がありますか?

58
BoltClock

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

おそらくすべきですが、それはしないであることがわかります:jQueryは:not()セレクターを拡張して 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プレビュー

セレクタのコンマ区切りのリストを:not()に渡すと、要素をフィルタリングできますリストされているどのセレクタとも一致しない

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

  • ユニバーサルセレクター(_*_)、オプションで namespace を使用
  • タイプセレクター(adivspanulli、etc)、with a namespace
  • 属性セレクター(_[att]_、_[att=val]_など)、オプションで namespace を使用
  • クラスセレクター(_.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の回避策はありますか、それともスクリプトに依存する必要がありますか?

    ありがたいことに、この場合はあります。有効なCSSにするためには、複数の:not()セレクターを次々とチェーンする必要があります。

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

    セレクターthatが大幅に長くなることはありませんが、不整合と不便さは明らかです。

    更新されたインタラクティブ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 *)
    _

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

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

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

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


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

79
BoltClock