Development Tip

내 jQuery : not () 선택기가 CSS에서 작동하지 않는 이유는 무엇입니까?

yourdevel 2020. 12. 25. 10:34
반응형

내 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다른 클래스 중 하나가없는 분야에 클래스를 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;
}

그리고 모든 것이 최신 브라우저에서 완벽하게 작동합니다.

대화 형 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 해결 방법이 있습니까 아니면 스크립트에 의존해야합니까?


:not()선택기가 jQuery에서는 작동하지만 CSS에서는 실패 하는 이유는 무엇 입니까? jQuery가 "CSS3 호환"이라고 주장하므로 두 곳 모두에서 동일하게 작동하지 않아야합니까? 아니면 제가 놓친 것이 있습니까?

Perhaps it should, but it turns out that it doesn't: jQuery extends the :not() selector such that you can pass any selector to it, no matter how complex it may be, and I suspect that the main reason for this is for parity with the .not() method, which also takes any arbitrarily complex selector and filters accordingly. It does in a way maintain a CSS-like syntax, but it extends from what's defined in the standard.

As another example, this works just fine (I know it's an incredibly ludicrous example compared to what's given in the question, but it's just for illustrative purposes):

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

Remember that passing a comma-separated list of selectors to :not() means filtering elements that don't match any of the listed selectors.

Now the :not() pseudo-class in Selectors level 3, on the other hand, is very limited by itself. You can only pass a single simple selector as an argument to :not(). This means you can pass only any one of these at a time:

  • Universal selector (*), optionally with a namespace
  • Type selector (a, div, span, ul, li, etc), optionally with a namespace
  • Attribute selector ([att], [att=val], etc), optionally with a namespace
  • Class selector (.class)
  • ID selector (#id)
  • Pseudo-class (:pseudo-class)

So, here are the differences between jQuery's :not() selector and the current standard's :not() selector:

  1. First and foremost, to answer the question directly: you can't pass a comma-separated selector list.1 For example, while the given selector works in jQuery as demonstrated in the fiddle, it isn't valid CSS:

    /* If it's not in the Α, Β or Γ sectors, it's unassigned */
    #sectors > div:not(.alpha, .beta, .gamma)
    

    Is there a pure CSS workaround for this or will I have to rely on a script?

    Thankfully, in this case, there is. You simply have to chain multiple :not() selectors, one after another, in order to make it valid CSS:

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

    It doesn't make the selector that much longer, but the inconsistency and inconvenience remain evident.

    Updated interactive jsFiddle preview

  2. You can't combine simple selectors into compound selectors for use with :not(). This works in jQuery, but is invalid CSS:

    /* Do not find divs that have all three classes together */
    #foo > div:not(.foo.bar.baz)
    

    You'll need to split it up into multiple negations (not just chain them!) to make it valid CSS:

    #foo > div:not(.foo), #foo > div:not(.bar), #foo > div:not(.baz)
    

    As you can see, this is even more inconvenient than point 1.

  3. You can't use combinators. This works in jQuery, but not CSS:

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

    This is a particularly nasty case, primarily because it has no proper workaround. There are some loose workarounds (1 and 2), but they almost always depend on the HTML structure and are therefore very limited in utility.

  4. In a browser that implements querySelectorAll() and the :not() selector, using :not() in a selector string in a way that makes it a valid CSS selector will cause the method to return results directly, instead of falling back to Sizzle (jQuery's selector engine which implements the :not() extension). If you're a stickler for performance, this is a positively minuscule bonus you'll definitely salivate over.

The good news is that Selectors 4 enhances the :not() selector to allow a comma-separated list of complex selectors. A complex selector is simply either a lone simple or compound selector, or an entire chain of compound selectors separated by combinators. In short, everything you see above.

This means that the jQuery examples above will become valid level 4 selectors, which will make the pseudo-class much, much more useful when CSS implementations begin supporting it in the coming years.


1 Although this article says that you can pass a comma-separated list of selectors to :not() in Firefox 3, you're not supposed to be able to. If it works in Firefox 3 as that article claims, then it's because a bug in Firefox 3 for which I can't find the ticket anymore, but it shouldn't work until future browsers implement future standards. Seeing how often that article is cited to date, I've left a comment to this effect, but seeing also how old the article is and how infrequently the site is being updated, I'm really not counting on the author coming back to fix it.

ReferenceURL : https://stackoverflow.com/questions/10711730/why-is-my-jquery-not-selector-not-working-in-css

반응형