All siblings selector

This is a thing that I needed so many times, that I’m sure many of you would benefit from it as well.

We do have next-sibling “+” and following-sibling “~” combinators, but there’s no way to get all of the siblings (previous and next).

I don’t have any character to propose as a combinator ("*" would be the best I think but it’s already used for something else).

If this breaks any rules or something please just remove the topic.

1 Like

Are you suggesting you would like to select all the elements that are siblings of element A or all the elements that are siblings of element A plus element A itself?

CSS has several proposals which would make either of these more plausible than they are today, but if you provide some code samples/use case we can see if we’ve missed something or explain how you can write them given proposals, as well as the state of those proposals.

Just the A siblings (without the A itself).

The perfect use case for this would be a situation, where you hover over an element, and you want to dim all other siblings (excluding the one you’re currently hovering).

Let’s say you have such markup:

<div class="gallery">
  <div class="gallery-item">...</div>
  <div class="gallery-item">...</div>
  <div class="gallery-item">...</div>

Then in CSS:

.gallery-item:hover X .gallery-item {
  opacity: 0.5

Where X would be all siblings selector.

I hope that clarifies a little.

Kind of like this?

Yes, kinda. But what you’re doing is triggering hover on parent element which is not always a good solution for this use case. For example if you have children positioned absolutely on the page and you can hover the parent but not hover any of the children.

Like this:

The issue that usually stops selectors like this from happening is that most of CSS is designed so browsers can display pages as they stream in from the network. (Usually called “single flow,” or something.) If you had code like this, for example:

li:siblings(.featured) {
  display: inline;

And while receiving the HTML from the network, <li class="featured"> came in, the browser would have to lay out and paint that part of the document again.

That said, this isn’t as true as it used to be. table-layout: auto and Flexbox requires more than one layout pass, and so do other proposed advanced layout modules. So this might be more plausible to implement than the last time CSS Selectors was being drafted.

Observation of those in the wild has shown us some problems, though:

  1. The layout can jump all over the place during loading, disorientating the user. And considering scripted DOM changes, user actions like resizing, and animations, it would be trivial for the layout to start thrashing around in deep corners of a large site’s codebase.

  2. Or like automatic table layout, the browser doesn’t render anything until that particular area is done, which is also terrible.

  3. Layout calculations can very easily get complex and slow; it makes it really easy for authors to write horribly-performing CSS that they might not notice on beefy desk/laptops. (This isn’t far-fetched; see the saga of text-rendering: optimizeLegibility.)

The CSS Working Group is pretty staunch about withholding powerful features that are easy to shoot yourself in the foot with. It sucks to hear it, but the language was designed from day one to limit the developer’s powers for better user experience on average. The expectation was most CSS would be written badly, and that’s pretty true. If 50% of all developers are below average, given the scale of the Web, that’s a lot of below-average CSS, and a lot of surface area for unintended disaster. By limiting how much a developer can do, it also limits how bad a developer can screw up.

To be clear, I would love this selector myself, I’m just pointing out why this sort of thing hasn’t succeeded in the past.

We just need to figure out how to solve these issues, kind of like how Container Queries evolved out of Element Queries. Maybe we could steal some concepts from GSS, since constraint-based layout usually has safety valves built in.


Thank you! Your answer is pretty informative. Is JavaScript the best option for such task of choosing all siblings?

Yep, pretty much. The easiest way of getting all sibling elements of yourElement would probably be:

Array.from(yourElement.parentNode.children).filter(el => el !== yourElement)