66

Usually, I'm good with CSS, but I can't seem to figure this one out. If I have a structure of

<div>
    <h2 class="open">1</h2>
    <h2>2</h2>
    <h2>3</h2>
    <h2>4</h2>
    <h2>5</h2>
</div>

how can I target all of the sibling h2s using the .open class with CSS? My main issue is that sibling selectors (.open + h2) will only target the h2 immediately following .open.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Chad
  • 5,308
  • 4
  • 24
  • 36

2 Answers2

128

You can select all the following siblings using ~ instead of +:

.open ~ h2

If you need to select all h2 elements that aren't .open whether they precede or follow .open, there is no sibling combinator for that. You'll need to use :not() instead:

h2:not(.open)

Optionally with a child combinator if you need to limit the selection to div parents:

div > h2:not(.open)
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Alright, that's what I needed to know. And I'm performing a function on the .open class, too, so I'd just have to do $('.open').siblings – Chad Aug 05 '12 at 02:19
  • 3
    While this post answers the question, some might also find this answer (http://stackoverflow.com/questions/1817792/is-there-a-previous-sibling-selector) useful just to confirm that the "general sibling selector" will not target previous siblings, only subsequent siblings. – Luke Jun 02 '15 at 01:54
  • Please note that `:not(.open)` can match elements regardless if `.open` is present. – Rudey Feb 27 '17 at 14:45
  • @Ruud Lenders: No, it can not. The entire point of :not(.open) is to not match elements that are .open. If you're talking about :not(.open) as a compound selector, i.e. without a qualifying type selector, then [99% of the time the explanation is that it's matching the *ancestors* of .open that are themselves not .open, and that the .open itself is inheriting styles from those ancestors, thereby giving the false impression that the .open itself is being matched by the selector](http://stackoverflow.com/questions/7084112/css-negation-pseudo-class-not-for-parent-ancestor-elements). – BoltClock Feb 27 '17 at 14:50
  • I meant it can match elements without the class being present on other elements, as opposed to `.open ~ h2` which only matches elements if `.open` itself is present on a preceding sibling. – Rudey Feb 27 '17 at 15:19
1

I know this isn't a direct answer to your question, but I've found it to be a much more efficient way to select siblings by simply selecting all the children of the parent, and specifying a unique class for the open as you have it there. So the code would be:

div h2 { } // apply the style for all "siblings" but really children
div h2.open { } // apply the style or cancel styles from the siblings

This works great for me and it doesn't require new css rules or anything special.

agrublev
  • 748
  • 1
  • 8
  • 22