2
<div class="abc"></div>

I need to delete this div if there is nothing in between the div tags means when div is empty.

I am approaching in CSS like this

div.abc:empty{display:none;}

But I have one problem if I use this method. If there is a single space between div, like <div> </div> :empty doesn't work.

div.abc { border: 1px solid red; height:50px; }
div.abc:empty{display:none;}
<div class="abc"></div>
<hr/>
<div class="abc"> </div>
ItsMe
  • 395
  • 2
  • 13
newCoder
  • 59
  • 2
  • Unfortunetely as of now there is no such thing but they are apparently working on it. – Tim Gerhard Nov 01 '21 at 09:51
  • Not possible as far as I know. You could look at https://stackoverflow.com/a/13147311/4174789 for some more info. It's due to the way how CSS was designed. It's *cascading*, meaning that you can style child elements based on their parents, but not vice versa. You really need JavaScript for that. – Bart Hofland Nov 01 '21 at 09:53

2 Answers2

3

As of November 2021 impossible without JavaScript. There is no trim in CSS (yet except in FireFox

Note this example will also hide divs that have pseudo class content

document.querySelectorAll(".abc")
  .forEach(div => div.hidden = div.textContent.trim() === "")
  
  // alternative if you want to use a class:
  // div.classList.toggle("hide",div.textContent.trim() === "")
div.abc { border: 1px solid red; height:50px; }
div.pscontent:after { content: "Also will be hidden"}
div.abc:empty{display:none;}
<div class="abc"></div>
<hr/>
<div class="abc"> </div>
<hr/>
<div class="abc pscontent"></div>

To handle pseudo class content we can do this:

const hideEmpty = (sel, testPseudoContent) => {
  const elems = document.querySelectorAll(sel)
  elems.forEach((elem,i) => {
    const text = [elem.textContent.trim()]
    if (testPseudoContent) {
      ["before", "after"].forEach(ps => text.push(window.getComputedStyle(elem, ps).getPropertyValue("content").trim()))
    }
    elem.hidden = text.join('').length === 0;
  })
};

hideEmpty('.abc')
hideEmpty('.def.pscontent', true)
div.abc {
  border: 1px solid red;
  height: 50px;
}

div.def {
  border: 1px solid green;
  height: 50px;
}

div.pscontent:after {
  content: "Don't hide this"
}
<div id="div1" class="abc"></div>
<hr/>
<div id="div2" class="abc"> </div>
<hr/>
<div id="div5" class="def pscontent"></div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • 1
    There is that API called `hidden`. I don't get why people keep writing their own CSS classes for something that is already built-in in every element. `div.hidden = div.textContent.trim() ===""` – connexo Nov 01 '21 at 10:14
  • @connexo - sure. I prefer the class but I see your point – mplungjan Nov 01 '21 at 10:19
0

Your code does work but in the near future because the Specification has changed to make :empty consider white spaces

Note: In Level 2 and Level 3 of Selectors, :empty did not match elements that contained only white space. This was changed so that that—given white space is largely collapsible in HTML and is therefore used for source code formatting, and especially because elements with omitted end tags are likely to absorb such white space into their DOM text contents—elements which authors perceive of as empty can be selected by this selector, as they expect. ref

Until then, there is a Firefox solution using -moz-only-whitespace

div.abc { border: 1px solid red; height:50px; }
div.abc:-moz-only-whitespace {display:none;}
div.abc:empty {display:none;}
<div class="abc"></div>
<hr/>
<div class="abc"> </div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415