CSS selector for something not inside something else

后端 未结 3 546
太阳男子
太阳男子 2020-12-30 23:48

I have some nested elements like this:

相关标签:
3条回答
  • 2020-12-31 00:14

    A little bit late to the party, and it might not match your use case, but this is what I ended up doing:

    HTML:

    <div class="foo">
        <div class="select-inside-this">
            <div class="not-inside-this">
                <div class="one select-this"></div>
            </div>
        </div>
    </div>
    <div class="select-inside-this">
        <div class="two select-this"></div>
    </div>
    <div class="three select-this"></div>
    

    CSS:

    .select-inside-this .select-this {
        background: blue;
    }
    .select-inside-this .not-inside-this .select-this {
        background: none;
    }
    

    The trick is to positively select the negative element and just undo the style.

    It'll work for simple use cases, at the very least.

    0 讨论(0)
  • 2020-12-31 00:17

    :not(.not-inside-this) and *:not(.not-inside-this) with the * are equivalent; in the case of the former, the universal selector is implied. See the spec.

    It is currently not possible to construct a CSS selector that matches elements that are not descendants of specific elements for the reasons given in the following questions:

    • CSS negation pseudo-class :not() for parent/ancestor elements
    • Is the CSS :not() selector supposed to work with distant descendants?

    The selector

    .select-inside-this :not(.not-inside-this) .select-this
    

    matches .select-this elements that are descendants of some element that is not .not-inside-this, which in turn is a descendant of .select-inside-this. It does not match .select-this elements that are not descendants of .not-inside-this within .select-inside-this.

    This means, first off, that your selector will incorrectly match the following:

    <div class="select-inside-this">
        <div class="bar">
            <div class="not-inside-this">
                <div class="select-this"></div>
            </div>
        </div>
    </div>
    

    ... because one of the ancestors of .select-this, .bar, is :not(.not-inside-this).

    Additionally, this implies at least three levels of nesting (though it could be more). In your example, there are no other elements between .two.select-this and its containing .select-inside-this, so it will never match that element. This is why James Donnelly suggests adding .select-inside-this > .select-this to account for that particular case.

    However it is still not possible to write a single complex selector using descendant combinators to match elements without a specific ancestor. The only way is to repeat the child combinator method with as many :not(.not-inside-this) as necessary, but this requires that you account for all possible cases. If you can't do that, then you're out of luck with CSS selectors.

    0 讨论(0)
  • 2020-12-31 00:21

    You can use the Child Combinator Selector > to specify direct children:

    .select-inside-this :not(.not-inside-this) .select-this,
    .select-inside-this > .select-this {
        /* style here /*
    }
    

    This selects any .select-this element which is not a descendent of any .not-inside-this element and also selects .select-this elements which are direct children of .select-inside-this elements.

    body > .select-inside-this :not(.not-inside-this) .select-this,
    body > .select-inside-this > .select-this {
      color: red;
    }
    <div class="foo">
        <div class="select-inside-this">
            <div class="not-inside-this">
                <div class="one select-this">
                    This should not be selected
                </div>
            </div>
        </div>
    </div>
    <div class="select-inside-this">
        <div class="two select-this">
            This should be selected
        </div>
    </div>
    <div class="three select-this">
        This should not be selected
    </div>

    0 讨论(0)
提交回复
热议问题