0

If I have two DIVs where I apply CSS using :empty so that if one DIV has content, then the other's background will change color, it works if the DIVs aren't nested. In the fiddle, type anything into the top white box, the other will turn yellow.

http://jsfiddle.net/7fwL26ox/7/

<div id="inner-div" contenteditable=true></div>
<div id="outer-container">
  
</div>

#outer-container {
    padding: 2em 0;
    background-color: #CCC;
}
#inner-div{
  border: 1px solid #000;
}
#inner-div:not(:empty) + #outer-container{
    background-color: yellow;
}

If I nest the DIVs, where the DIV that is empty and changes content, is nested inside the DIV that changes color, it no longer works (input is outlined in the fiddle).

http://jsfiddle.net/vpcwtg7m/1/

<div id="outer-container">
   <div id="inner-div" contenteditable=true></div>
</div>

#outer-container {
    padding: 2em 0;
    background-color: #CCC;
}
#inner-div{
  border: 1px solid #000;
}
#inner-div:not(:empty) + #outer-container{
    background-color: yellow;
}

I would have expected in the second fiddle, that the background will also change to yellow. Exact same CSS, just the placement of the DIVs has changed. Cheers!

jookyone
  • 141
  • 7
  • 2
    This is because you are using a sibling selector +, but it's nested and has no sibling to select. That's why it works in your first example because both DIVS are siblings. I would recommend using JS, as even in your first example if you enter text, and then delete everything, so it's "empty" it's still acting as if it's not empty. – Carl Feb 01 '23 at 00:52
  • I had it working with JS, but my customer asked for a "no code change" solution and found not(:empty) in my research. Thank you for the explanation. – jookyone Feb 01 '23 at 06:29

1 Answers1

2

The + in your CSS selector is an adjacent sibling combinator. It targets the next sibling after itself.

Your first example works because #outer-container is the next sibling:

<div id="inner-div" contenteditable=true></div>
<div id="outer-container">

When you rearrange your HTML the CSS is targeting a sibling that no longer exists:

<div id="outer-container">
   <div id="inner-div" contenteditable=true></div>
   <!-- CSS is looking for your outer-container div here, as the next sibling after inner-div -->
</div>

To style a parent based on the child, you'll have to use the new :has() pseudo class that is still gaining browser support:

#outer-container {
  padding: 2em 0;
  background-color: #CCC;
}

#inner-div {
  border: 1px solid #000;
}

#outer-container:has(#inner-div:not(:empty)) {
  background-color: yellow;
}
<div id="outer-container">
  <div id="inner-div" contenteditable=true></div>
</div>
Zach Jensz
  • 3,650
  • 5
  • 15
  • 30