Home > Net >  How to hide parent HTML element only if child HTML element is empty, using only CSS?
How to hide parent HTML element only if child HTML element is empty, using only CSS?

Time:07-05

Consider the situation:

<section><h1>TITLE</h1>
...
<div >

Lorem ipsum dolor sit amet consectetur, adipisicing elit. Itaque minima repudiandae sequi ex voluptatem illo, hic tempora recusandae commodi, similique earum laudantium deleniti atque placeat nemo, aperiam ullam dicta quae.

</div>
</section>

<section><h1>TITLE-TO-HIDE</h1>
...
<div >
</div>
</section>

My question is how do you hide the entire <section>...</section> with the empty child div.section-body ? using only CSS, if possible ? else can someone explain why it isn't possible and/or provide a way to achieve this behavior in whatever way it is possible ?

CodePudding user response:

You can select a parent element with :has but it only supported by Safari and the lastest chrome versions (105 , CanIUse).

You can select an empty element with the :empty pseudo class. Note that you need the div to be empty with no space, according to MDN or CanIUse :

The :empty pseudo-class was changed to act like :-moz-only-whitespace, but no browser currently supports this yet.

.body-section{
  width:100px;
  height:100px;
  border:1px solid black;
  margin-bottom:5px;
}
.body-section:empty{
  display:none;
}
<div >A</div>
<div ></div>
<div >C</div>
<div > </div>

CodePudding user response:

I would say that pure CSS is probably not the best way to do what you aim for. This type of condition is easily handled with proper code, while stylesheet methods are very confused from a browser to another.

I can propose you a very simple Javascript solution, on the snippet below I removed the section but you can just hide it aswell using .style.display="none" instead of removeChild.

function checkEmpty(){
const sectionBody = document.getElementsByClassName("sectionBody");

Array.from(sectionBody).forEach((el) => { //loop on every div of the class
if (el.textContent.trim() === '') //check if the div is empty
{
var section = el.parentElement;
section.parentNode.removeChild(section); //remove parent section of the current div 
}    
});
}
<section><h1>TITLE</h1>
...
<div >

Lorem ipsum dolor sit amet consectetur, adipisicing elit. Itaque minima repudiandae sequi ex voluptatem illo, hic tempora recusandae commodi, similique earum laudantium deleniti atque placeat nemo, aperiam ullam dicta quae.

</div>
</section>

<section><h1>TITLE-TO-HIDE</h1>
...
<div >

</div>
</section>

<br>
<input type="button" onclick="checkEmpty()" value ="Remove empty section(s)">

CodePudding user response:

CSS can only traverse downward, a child can never apply a style to its parent/previous siblings.

So your best case scenarion is to place .section-body as first child and hide every sibling. It'll not hide section

.section-body:empty ~ * {
    display: none;
}
<section>
  <div >
      Lorem ipsum dolor sit amet consectetur, adipisicing elit. Itaque minima repudiandae sequi ex voluptatem illo, hic tempora recusandae commodi, similique earum laudantium deleniti atque placeat nemo, aperiam ullam dicta quae.
  </div>
  <h1>This will not be hidden</h1>
</section>
<section>
  <p>Down side siblings can't be selected</p>
  <div ></div>
  <h1>This will be hidden</h1>
</section>
<section>
  <div >
  </div>
  <p>Having new line is not empty</p>
</section>

<section>
  <div ></div>
  <h1>This will be hidden.</h1>
</section>

Let examin our "little hack", .section-body:empty ~ * will select every :empty tag that have a class section-body, we can get next sibligs with ~ and using * will select all of them.

Cons:

  • You need to change structure
  • If you have new lines, spaces or anything , this will not be empty

So a betther solution is to use javascript

And here is simple vanilla javascript solution

document.querySelectorAll("section > .section-body").forEach(function (el) {
    if (el.textContent.trim() === '') {
        el.parentNode.style.display = "none";
    }
});
 <section>
    <h1>TITLE</h1>
    <div >
        Lorem ipsum dolor sit amet consectetur, adipisicing elit. Itaque minima repudiandae sequi ex voluptatem illo, hic tempora recusandae commodi, similique earum laudantium deleniti atque placeat nemo, aperiam ullam dicta quae.
    </div>            
</section>
<section>
    <h1>TITLE 2</h1>
    <div >                
    </div>
</section>

  • Related