1

How could I use the :has selector to style a sibling?

In this example, the logic is: If the parent has a child with the class child1, child2 should be green.
but I can't seem to get it working- nor any :has selector for that matter, but sources online give conflicting syntaxs. I'm confused by it.

.parent {
  height: 100px;
  width: 200px;
  font-size: 10px;
}
.child1, .child2 {
  width: 100px;
  height: 50px;
  background-color: red;
  border: 2px solid black;
}
.child1 {
background-color: green
}

.parent:has(.child1) > .child2 {
  background-color: green;
}
<div class="parent">
  <div class="child1">
    this is child1
  </div>
  <div class="child2">
    this is child2
  </div>
</div>
Josh Silveous
  • 479
  • 2
  • 6
  • 16
  • 2
    What browser are you using? Even as of November 2022, not all browsers support `:has()` yet, like FIrefox, and don't forget the millions of iOS and Android users who won't or can't update to Safari 16 and Android Chrome 105. – Dai Nov 09 '22 at 20:13
  • 1
    You seem to be searching more for a "previous sibling" selector, rather than `:has` which can be used as a parent selctor – j08691 Nov 09 '22 at 20:14
  • 1
    @j08691 `:has` can be used to select previous siblings, it's just kinda complicated. – Dai Nov 09 '22 at 20:14
  • @Dai ah, that'd be it. I didn't realize FireFox doesn't support it, given all the coverage it's gotten recently. – Josh Silveous Nov 09 '22 at 20:16
  • 1
    You don't need `:has` at all - you can just do `div.parent > div.child1 + div.child2 { background-color: green; }` - though your post doesn't say what should happen if there are _other_ child elements, or if `.child1` exists but `.child2` does not, etc. – Dai Nov 09 '22 at 20:17
  • @Dai in this case, both child elements will always exist in that order, and there are always other children too. The goal is to select child2 when child1 was being hovered, something like `.parent:has(child1:hover) > child2 { ... }`. I am not very familiar with using `+`, I'll have to look into that. – Josh Silveous Nov 09 '22 at 20:20
  • 1
    `.child1:hover + .child2 {}` – Temani Afif Nov 09 '22 at 20:25
  • 1
    Then use `div.parent > div.child1:hover + div.child2 { background-color: green; }` - you only need `:has()` if you want to style/select an ancestor or preceding sibling of a another element - but the scenario you've described is about styling a _subsequent_ sibling of an element, both sharing the same parent: that's already handled by the `+` (adjacent/next-sibling) and `~` (general-sibling) combinators. – Dai Nov 09 '22 at 20:25
  • @Dai That clears up my confusion. Unfortunate that there's no way to select previous siblings without `:has()`, as that would be useful for a personal project of mine. My goal is to have two seperate divs, side-by-side, which will both `scale` up to 120% when either is hovered on, without using JS. Seems I can use the sibling selector to accomplish half of that. – Josh Silveous Nov 09 '22 at 20:31
  • For that, use `div.parent > div.child1:has( + div.child2:hover ), div.parent > div.child1:hover + div.child2 { transform: scale(1.2); }` (though this will only work in Blink/Chromium and Webkit browsers for now). Another option is to add a `
    ` to wrap only `child1` and `child2` (with `display: contents;`) and add a `:hover` rule to that?
    – Dai Nov 09 '22 at 20:39
  • @Dai Never used `display: contents`, but the descriptions I find online make it seem like exactly what I need. If the scale effect will be applied to the children as individuals, rather than the whole div, then that's a great solution! – Josh Silveous Nov 09 '22 at 20:47

0 Answers0