56

Consider the following html:

<div> <div class="iwant" /> <div class="idontwant" /> </div> <div> <div class="iwant" /> </div> 

I'm interested in a selector (for crawling content so I can't modify html) that would select all iwant that DO NOT have sibling with class idontwant.

0

5 Answers 5

80

There is no sibling selector to match elements (or not) by class.

The closest selector I can think of is

.iwant:only-child 

But this selector means that there cannot be any other elements besides that div class="iwant" as children of the parent div, regardless of type or class. This may fulfill your need depending on the structure of your HTML though, so it's worth a try. If class names are a problem for you, though, then there probably isn't much of a solution, because there isn't an :only-of-class pseudo-class in CSS which filters by class and ignores the rest.

Sign up to request clarification or add additional context in comments.

1 Comment

It might be a solution but I prefer something more general because there might be extra divs. Good thinking though.
22

If anyone still needs this, I found this answer . Based on it and on :not pseudo-class, the initial requirement can be accomplished using something like:

div:not(:has(+ .idontwant)) .iwant { ... } 

This approach has an advantage over the general sibling combinator: It also matches backwards, meaning something like:

<div> <div class="idontwant" /> <div class="iwant" /> </div> 

(so if you have the .idontwant element first -> case which would be ignored by the general sibling combinator)


Explanation:

  1. div:has(+ .idontwant) would match any div that has a direct sibling with the class idontwant
  2. div:not(:has(+ .idontwant)) matches any div that doesn't have a direct sibling with class idontwant
  3. All is left to do is search in the div that doesn't have a direct sibling with the class idontwant for the class we want.

The selector is quite weird and big, but it does the job, and I think there are (specific) cases where it is quite needed.


Edit (from comments): If anyone needs to style an element only if it has a specific sibling (or if it doesn't) you can still use the :has Pseudo-class to accomplish it (check snippet):

const toogleHasClassEl = document.getElementById("toogleHasClass") toogleHasClassEl.onclick = () => toogleHasClassEl.classList.toggle("specificclass")
div:has(.specificclass) .stylethis { background: orange } div:not(:has(.specificclass)) .stylethis { background: yellow } div:has(.stylethis) .specificclass { background: red }
<div> <div class="stylethis">style this</div> <div id="toogleHasClass" class="specificclass">if this has `specificclass` class (click to toggle)</div> </div> <hr/> <div> <div class="stylethis">style this different</div> <div class="thisdoesnthaveclass">if this doesn't have specific class</div> </div> <hr/> <div> <div class="stylethis">style this different (if alone and therefore doesn't have specific sibling)</div> </div>

5 Comments

Promising, but I am looking for a way to style .idontwant based on the presence of .iwant. That seems slightly more complicated, more like impossible. It seems that for some reason you are able to select an next sibling but not a previous sibling.
Hmmm... Not sure I understood what you want to accomplish. Could you give an example of a full element you would like to target, and maybe one you wouldn't?
I have a div that contains two divs sometimes the second div has a certain class, I would like to style the first div depending on if the second div has that class.
I added an edit with a snippet. Could that be what you are looking for?
yes that was it, I needed to remove the + from the the :has() and it works. Now I have to find where I used Js to solve this issue an implement this instead, thanks!
5

There's no negative-sibling CSS selector. Use the sibling selector to set new styles, then reset the styles at the .idontwant:

div.iwant { /*Set CSS here*/ display: inline; } div.iwant ~ div.idontwant { /*Reset CSS*/ display: block /* Default of DIV is block*/ } 

3 Comments

That's redundant since each class is mutually exclusive.
@BoltClock What do you mean by that? The div.iwant ~ div.idontwant selector is more specific than div.iwant.
I'm not setting styles, I want to get those element for crawler and I would prefer to do it in one query.
5

There's no good way to target an item without a specific sibling item. But you can use .iwant:last-child to target items that doesn't have a subsequent sibling.

Example: http://codepen.io/martinkrulltott/pen/YyGgde

Comments

0

This also might be helpful - if the element you want is always last-child:

div:last-child:not(.idontwant) { } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.