24

Is it possible to hide a parent element, if its child is empty? I know there is the :empty selector, but it only works, if the parent doesn't contain anything, including HTML elements.

This is my HTML:

<div class="row">
    <div class="center">
        <span class="text-danger label-promotion"><strong></strong></span>
    </div>
</div>

And my CSS, which sadly doesn't work this way, but I think you get what I'm trying to do:

.label-promotion:empty {
    display: none;
}

I want the <span> not to appear if is empty and I'd like to avoid JS for this. Is that possible?

Sean
  • 6,873
  • 4
  • 21
  • 46
TheKidsWantDjent
  • 1,179
  • 1
  • 9
  • 20
  • 1
    It isn't empty because there is a `` in there. Does it have to be there? (edit) Sorry, misread the top of the question. No, you cannot affect the parent based on what the child is doing. That is that **cascading** part of ***C*ascading *S*tyle *S*heet** – Joe Lissner Mar 30 '17 at 15:27
  • 7
    You could remove the strong element and assign a font-weight: bold to the span element. Doing so you could hide the whole span with span:empty { display: none; } – Fabrizio Calderan Mar 30 '17 at 15:29

2 Answers2

16

You can use has() (not yet supported in Firefox):

.label-promotion:has(> strong:empty) {
    display: none;
}

If the child of .label-promotion will always be a <strong>, you can do:

.label-promotion strong:empty {
    display: none;
}

to hide the <strong>. However, you can not hide the <span> itself with CSS. See this answer to a similar question: I would like to hide my outer div if inner div is empty

Stan James
  • 2,535
  • 1
  • 28
  • 35
FuturrCoder
  • 307
  • 3
  • 7
2

I'd like to avoid JS for this

Yes, I agree, it's always better to have a pure CSS solution.

But in this instance all you need to do is:

  • find all the .label-promotion <spans>
  • loop through them, checking if each has an empty <strong>
  • if it does, add to the <span> the class .is-empty

Working Example:

// Find all the .label-promotion <spans>
const labelPromotions = document.querySelectorAll('.label-promotion');

// Loop through them... 
for (labelPromotion of labelPromotions) {

  let strong = labelPromotion.getElementsByTagName('strong')[0];
  
  // ... checking if each has an empty <strong> 
  if (strong.textContent === '') {
    
    // If it does, add to to the <span> the class .is-empty
    labelPromotion.classList.add('is-empty');
  }
}
span {
  display: inline-block;
  width: 32px;
  height: 32px;
  line-height: 32px;
  text-align: center;
  border: 1px solid rgb(255, 0, 0);
  vertical-align: middle;
}

.is-empty {
  display: none;
}
<span class="text-danger label-promotion"><strong>A</strong></span>
<span class="text-danger label-promotion"><strong></strong></span>
<span class="text-danger label-promotion"><strong>C</strong></span>
<span class="text-danger label-promotion"><strong>D</strong></span>
<span class="text-danger label-promotion"><strong></strong></span>
<span class="text-danger label-promotion"><strong></strong></span>
<span class="text-danger label-promotion"><strong>G</strong></span>
Rounin
  • 27,134
  • 9
  • 83
  • 108