1

I have a part of my HTML that is similar to the one below, and I must select only the elements that do not have any ancestors with a specified class. The project I work on is pretty big and I think I should not post here all the code, I think that would be beyond the purpose of StackOverflow.

What I want is filtering the elements by all their ancestors, not only by their parents. I have tried this:

// This colors two of the <span> elements instead of one. It colors the ".a > .b" <span> and this behavior seems wrong to me.
$(":not(.a) .b:not(.a)").css("color", "red");

// This call only colors the border of the ".b" <span> which, I think, is the correct behavior and should be the behavior of the call above.
$(":not(.a) > .b:not(.a)").css("border-color", "blue");
span {
    border: 0.1rem solid gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="a">
  <span class="b">.a > .b</span> <!-- Why does this <span> element become red? -->
  <span class="a b">.a > .a.b</span>
</div>
<div>
  <span class="b">.b</span>
  <span class="a b">.a.b</span>
</div>

I have put the code above in this JSFiddle. I have tested the two selectors using the document.querySelectorAll function without jQuery and the behavior is the same.

Thank you very much! :-)

silviubogan
  • 3,343
  • 3
  • 31
  • 57

2 Answers2

3
:not(.a) .b:not(.a)

Selects all elements with class b, but without class a, that has any ancestor without class a, for example, <body> & <html>.

:not(.a) > .b:not(.a)

Selects all elements with class b, without class a, that hasn't a direct parent with class a.

A. Wolff
  • 74,033
  • 9
  • 94
  • 155
Amit
  • 45,440
  • 9
  • 78
  • 110
  • Thank you for the answer! It explains the behavior. Do you know how can I change the selector so that it selects all elements with class `b`, but without class `a`, that has **all the ancestors** without class `a`? Is it even possible? – silviubogan Nov 23 '15 at 10:42
  • @silviubogan not sure what you mean by that. looks like your 2nd version (the one the uses `>`) is what you wanted, isn't it? – Amit Nov 23 '15 at 10:43
  • @BoltClock gave me the answer I was looking for, I tested his selector and it works. Thank you anyway! `:-)` – silviubogan Nov 23 '15 at 11:26
1

Do you mean to select .b elements that

  • are not .a, and
  • do not have any ancestors that are .a?

Then this is only doable with jQuery (learn more):

$(".b:not(.a, .a *)")

If you need to do this in CSS, you can either add a class using jQuery with the above selector, or use an override:

.b {
  /* Style all .b elements */
}

.a .b, .a.b {
  /* Override the previous rule */
}
Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356