The CSS :empty
pseudo-class selects any element that does not contain children for a given selector.
/* Changes the background color of every empty section element */
section:empty {
background-color: tomato;
}
If we were to run that code on a page, the CSS would look for a <section>
element that contains no content between the tags. That might look something like this:
<section>
<p>I have content</p>
</section>
<section>
<p>I have content, too!</p>
</section>
<section> // HIGHLIGHT
<!-- No content, just an HTML comment. 🎺 -->
</section>
What makes an element “empty”?
An element with nothing between its tags is empty.
<div></div>
That includes if an element contains a code comment.
<div><!--I'm still empty, even with this comment. --></div>
And if the CSS for the element has generated content
— as from a pseudo-element like ::before
or ::after
— it is also still considered empty.
div::before {
content: "Yep, still empty!;"
}
Elements with children (aka “non-empty” elements)
An element is said to have “children” if it contains another element node, text or even textual white space in between its tags. The elements in the following code are considered “non-empty” ones.
<article>
<h1>I'm a child of this article element.</h1>
</article>
<p>This text is considered a child.</p>
<!-- Even whitespace between tags qualifies this element as "non-empty" -->
<h1> </h1>
But be careful! Code editors may create unwanted white space, making an otherwise empty element a non-empty one.
<section>
<!-- The white space in this element makes it a "non-empty" element -->
</section>
:-moz-only-whitespace
s
It now acts like :empty
was updated to behave like Mozilla’s prefixed :moz-only-whitespace
pseudo-class in the Selectors Level 4 specification. Like :empty
, :moz-only-whitespace
selects empty elements. The difference is that :moz-only-whitespace
also selects elements that only contain textual white space. The spec explains it incredibly well:
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.
So, yeah. This change is more likely to make :empty
behave the way we expect, so that even when there are certain elements (e.g. <br>
) or white space from formatting inside of an element, they won’t prevent an element from being considered empty.
However, there is currently no browser support for this change.
It’s not great for form validation
You’d think it would be! But if we try to apply :empty
to an <input>
and hope to make it red to show the user it needs to be completed, that input will always be red.
Why is that? It’s because :empty
searches for empty container content, but inputs are considered empty elements even though content can be typed into them.
Demo
Empty nav item
In this example, an li
element in the navigation is removed when it has no content. Click the button to toggle the empty state for the third navigation item.
Empty API field
Here the :empty
pseudo-selector helps us display a direction to the user in order to load a joke into the same field.
Browser support
IE | Edge | Firefox | Chrome | Safari | Opera |
---|---|---|---|---|---|
9+ | Yes | Yes | Yes | Yes | Yes |
Android Chrome | Android Firefox | Android Browser | iOS Safari | Opera Mobile |
---|---|---|---|---|
Yes | Yes | Yes | Yes | Yes |
Support for matching elements with whitespace
IE | Edge | Firefox | Chrome | Safari | Opera |
---|---|---|---|---|---|
No | No | No | No | No | No |
Android Chrome | Android Firefox | Android Browser | iOS Safari | Opera Mobile |
---|---|---|---|---|
No | No | No | No | No |