Reputation: 3085
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
.
Upvotes: 55
Views: 41594
Reputation: 3386
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:
div:has(+ .idontwant)
would match any div
that has a direct sibling with the class idontwant
div:not(:has(+ .idontwant))
matches any div
that doesn't have a direct sibling with class idontwant
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>
Upvotes: 22
Reputation: 3890
This also might be helpful - if the element you want is always last-child:
div:last-child:not(.idontwant) {
}
Upvotes: 0
Reputation: 1956
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
Upvotes: 5
Reputation: 723448
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.
Upvotes: 79
Reputation: 348972
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*/
}
Upvotes: 5