Css3 :Not() Selector to Test Parent's Class

css3 :not() selector to test parent's class

Combinators such as >, + and space for descendant aren't allowed within :not() in CSS; they're only allowed as a jQuery selector. You can find out more in this other question.

That said, you may be able to use :not() on the li alone, and move out the > a part; however this will depend on the structure of your ul and li elements:

li:not(.active) > a {
color: grey;
}

For example, you can always chain other selectors, such as .span3 if you want to limit it to a elements with li parents of that class only:

li.span3:not(.active) > a {
color: grey;
}

Keep in mind, though, that you can only rely on using :not() in this manner if you have control over the markup or the structure is at least predictable (e.g. you know what kind of elements the parents are). In your case for example, you're only looking at li.span3 > a, and applying styles only when the li.span3 does not have the active class. With this information you can construct a selector like one of the above, which should work as expected.

Select only elements that don't have a parent with defined class

I don't think you can use combinator selectors with :not as stated in the documentation:

This selector only applies to one element; you cannot use it to
exclude all ancestors. For instance, body :not(table) a will still
apply to links inside of a table, since <tr> will match with the
:not() part of the selector.

You could try something like this:

div {  background-color: red;  padding: 5px;}
.child { background-color: green; padding: 5px;}
.dontSelect .child { background-color: initial;}
<div>  <div class="child">    Select this  </div>  <div class="dontSelect">    <div>      <div class="child">        Don't select this      </div>    </div>  </div></div>

CSS :not() selector. Apply style if parent does not exist

You're selecting wrong elements. No reverse lookups possible, see here:

div:not(.container1) > .myDiv {  color: red;}
<div class="container1">  <div class="myDiv">Div 1</div></div>
<div class="container2"> <div class="myDiv">Div 2</div></div>

CSS negation pseudo-class :not() for parent/ancestor elements

Doesn't this read, "Select all h1 elements that have an ancestor that is not a div element...?"

It does. But in a typical HTML document, every h1 has at least two ancestors that are not div elements — and those ancestors are none other than body and html.

This is the problem with trying to filter ancestors using :not(): it just doesn't work reliably, especially when the :not() is not being qualified by some other selector such as a type selector or a class selector, e.g. .foo:not(div). You'll have a much easier time simply applying styles to all h1 elements and overriding them with div h1.

In Selectors 4, :not() has been enhanced to accept full complex selectors containing combinators, including the descendant combinator. Whether this will be implemented in the fast profile (and thus CSS) remains to be tested and confirmed, but once it is implemented, then you will be able to use it to exclude elements with certain ancestors. Due to how selectors work, the negation has to be done on the element itself and not the ancestor in order to work reliably, and therefore the syntax will look a little different:

h1:not(div h1) { color: #900; }

Anyone who's familiar with jQuery will quickly point out that this selector works in jQuery today. This is one of a number of disparities between Selector 3's :not() and jQuery's :not(), which Selectors 4 seeks to rectify.

Is there a CSS parent selector?

There is currently no way to select the parent of an element in CSS in a way that works across all browsers.

That said, the Selectors Level 4 Working Draft includes a :has() pseudo-class that will provide this capability. It will be similar to the jQuery implementation.

li:has(> a.active) { /* styles to apply to the li tag */ }

As of 2022, it is only supported by Safari, and by Chromium browsers behind a flag.

In the meantime, you'll have to resort to JavaScript if you need to select a parent element with full cross-browser support.

Is the CSS :not() selector supposed to work with distant descendants?

Is this supposed to work like I think it should?

No, the behavior you're seeing is correct.

In your last example, although the <blockquote> contains a <p>, it's the <blockquote> itself that's matching *:not(p), as well as the condition that it must be a descendant of the <div>, which it is. The style is applied only to the <blockquote>, but it is then inherited by the <p> inside it.

The <p> element itself still counts against the negation, so the <p> itself is still being excluded from your selector. It's just inheriting the text color from its parent, the <blockquote> element.

Even if none of its relatively close ancestors matched the selector, you have elements like html and body to worry about as well — although you could probably just tack on a body selector in the very beginning:

body div...

This is why I often strongly advise against using the :not() selector for filtering descendants, especially when not qualified with a type selector (like div in your example). It doesn't work the way most people expect it to, and the use of inherited properties like color only serves to compound the problem, on top of making it even more confusing for authors. See my answers to these other questions for more examples:

  • Why doesn't this CSS :not() declaration filter down?
  • CSS negation pseudo-class :not() for parent/ancestor elements

The solution to the problem described is to simply apply a different color to <p> elements. You won't be able to simply exclude them with a selector because of inheritance:

/* Apply to div and let all its descendants inherit */
div {
color: red;
}

/* Remove it from div p */
div p {
color: black;
}

On Selectors Level 4: yes, :not() has indeed been enhanced to accept full complex selectors that contain combinators. Essentially, this means (once browsers begin implementing it) you will be able to write the following selector and have it do exactly what you want:

p:not(div p) {
color: red;
}

In case anyone is interested, this works in jQuery today.

Complex CSS selector for parent of active child

Unfortunately, there's no way to do that with CSS.

It's not very difficult with JavaScript though:

// JavaScript code:
document.getElementsByClassName("active")[0].parentNode;

// jQuery code:
$('.active').parent().get(0); // This would be the <a>'s parent <li>.

CSS selector to exclude all children where any parent at ANY LEVEL has a class

Find all the elements (all), then the elements with no-material on the element or its parent (no), then remove those in the second from those in the first to find those that remain (yes).

const difference = (a, b) => a.filter(elt => b.indexOf(elt) === -1);  const all = document.querySelectorAll("input");const no = document.querySelectorAll(".no-material input, input.no-material");
const yes = difference([...all], [...no]);
console.log(yes.map(elt => elt.name));
<main style="display: none;">
<!-- Not selectable --> <div class="no-material"> <input name="no-1"> </div>
<div> <input name="no-2" class="no-material"> </div>
<div> <label class="no-material"> <input name="no-3"> </label> </div>
<div> <label class="no-material"> <span> <input name="no-4"> </span> </label> </div>
<div> <label> <span class="no-material"> <input name="no-5"> </span> </label> </div>
<!-- Selectable --> <div> <input name="yes-1"> </div>
<div> <input name="yes-2"> </div>
<div> <label> <input name="yes-3"> </label> </div>
<div> <label> <span> <input name="yes-4"> </span> </label> </div>
<div> <label> <span> <input name="yes-5"> </span> </label> </div>
</main>


Related Topics



Leave a reply



Submit