The CSS pseudo-class :empty to select elements with no content

- 👤 Andrés Cruz

🇪🇸 En español

The CSS pseudo-class :empty to select elements with no content

When I started working with more complex layouts, I had to deal with containers that appeared "empty" but still took up space on the screen. At that point, I discovered that the :empty pseudo-class could save me a lot of time... although I also struggled quite a bit to understand exactly what CSS considers "empty." In this guide, I'll tell you everything so you don't go through the same thing.

 What exactly does :empty select?

Formal definition: no child nodes or text (including spaces)

:empty selects elements that contain no child nodes:

  • no HTML elements.
  • no text.
  • not even spaces, line breaks, or tabs.

This means that something like this:

<div></div>
<p></p>

Is indeed :empty, but the following is not:

<div> </div> <!-- A space already breaks :empty -->
<p>Hi</p> <!-- Text -->
<div><br></div> <!-- Has a child -->
<div><!-- comment--></div> <!-- comment = node -->

When I first discovered it, I thought that <div> </div> would be considered empty... but no: that small space already invalidates it.

What doesn't count as content (comments, pseudo-elements, etc.)

Something interesting is that pseudo-elements do not affect the empty state:

div:empty::before {
 content: "empty";
}

Even if visual content is generated, the element is still :empty at the time the rule is evaluated.

Surprising behavior: spaces, line breaks, etc.

It is very common for code editors, template generators, or CMSs to insert line breaks without you noticing:

<div> </div>

Visually it looks empty... but it contains a text node with a line break → therefore it does not match :empty.

In this post, we will see how the little-used and known :empty pseudo-class works and how to use it.

How does the :empty pseudo-class work in CSS?

 The :empty pseudo-class allows defining rules for those elements that do not have any children (other elements) within them, no text, or content in general; the following elements that can be represented (selected) by the :empty pseudo-class are shown below:

Without elements and without text:
<p></p>
<div></div>

The :empty selector or pseudo-class represents elements that have no children/nodes or content (including comments)

 The use of the :before or :after pseudo-classes does not count as content

 The previous elements can be represented through the :empty pseudo-class and therefore define their own style rules:

p:empty, div:empty 
{background: blue;
/*...something else*/
}

 The following elements do not meet the condition of being "empty" and are not selected by the :empty pseudo-class:

With elements<div><p>Element with some text</p></div>
With text<p>Element with some text</p>

 Let's look at a series of possible uses with the :empty pseudo-class:

Examples About :empty

Empty divs or containers

A classic use is to visually mark empty containers for interface debugging:

div:empty { background: red; height: 50px;}

If you've ever tried to lay out something and a "ghost rectangle" appeared, you'll know how useful this is for identifying boxes without content.

Empty table cells (td)

In large tables, it is practical to highlight cells without data:

td:empty { background: #eee;}

This helps a lot when working with imported or automatically generated data and you want to check where the content is incomplete.

Use with ::before / ::after for placeholders or messages

Although it may sound contradictory, you can use :empty::before to display messages in elements without content:

div:empty::before { content: "This element is empty."; color: #555; font-style: italic;}

I used it once to show temporary placeholders in an administration panel where some modules loaded information after an AJAX request.

The :empty pseudo-class to define boxes (DIVs) with different rules

 We can use rules like these:

div:empty{ background: red;}

 To differentiate between containers or boxes that do not contain any element or text (in red) through colors, shapes, borders, etc., from those that do have elements or text (in blue):

<div></div><div><p></p></div><div><br></div><div>Algún texto.</div><div><p>Más texto.</p></div><div></div><div></div><div><img src=""/></div><div></div>

 The :empty pseudo-class in conjunction with other pseudo-classes

 We can apply multiple pseudo-classes (nesting) in the same rule, for example, we can use the :before pseudo-class after the :empty pseudo-class and in this way define content when the elements are "empty" even if it sounds a bit contradictory:

div:empty{ background: red;}div:empty:before{ content:"Este elemento se encuentra vacío."}

 The HTML:

<div></div><div><p></p></div><div><br></div><div>Algún texto.</div><div><p>Más texto.</p></div><div></div><div></div><div><img src=""/></div><div></div>

 To define empty spaces in a table

 In this last example we will see how to differentiate between cells that are empty (<td></td>) or lacking elements, from those that do contain some information:

td:empty{ background: #DDD;}

 The HTML:

<table> <tr> <th>House Baratheon</th> <th>House Greyjoy</th> <th>House Stark</th> <th>House Martell</th> <th>House Tully</th> </tr> <tr> <td>Stannis Baratheon</td> <td></td> <td>Arya Stark</td> <td></td> <td>Cathelyn Tully</td> </tr> <tr> <td>Renly Baratheon</td> <td>Balon Greyjoy</td> <td></td> <td></td> <td></td> </tr> <tr> <td>Joffrey Baratheon</td> <td>Maron Greyjoy</td> <td>Bran Stark</td> <td>Trystane</td> <td></td> </tr> <tr> <td>Tommen Baratheon</td> <td></td> <td>Rickon Stark</td> <td>Quentyn</td> <td></td> </tr> <tr> <td></td> <td></td> <td>Eddard Stark</td> <td>Arianne</td> <td>Bryden Tully</td> </tr> </table>

Real use cases and best practices

Hiding empty containers in dynamic sites / CMS

When a CMS leaves containers without content (something very common), you can clean them up like this:

section:empty { display: none;}

This keeps the layout clean without having to manually check each module.

Layout cleaning / avoiding unwanted white spaces

During template layout, orphan containers sometimes appear that generate strange spaces. A simple rule with :empty helps detect them:

*::before,*::after { /* styles */}div:empty { outline: 1px dashed red;}

Conditional styling in dynamic interfaces

If you dynamically generate cards, notifications, or entries, you can ensure that containers without content have an alternative style or are not displayed.

Limitations and things to consider

What breaks the "empty" state. Anything on this list invalidates :empty:

  • text (even a single letter),
  • spaces, tabs, line breaks,
  • HTML comments,
  • invisible text nodes,
  • child elements (<br>, <p>, <img>, etc.).

Browser compatibility

Luckily, :empty has excellent compatibility in modern browsers. It works on Chrome, Firefox, Safari, Edge, and virtually all current browsers.

When to consider alternatives

If you need to ignore automatically generated white spaces or line breaks, :empty is not useful. Alternatives:

  • Clean the content via backend or JavaScript.
  • Use dynamic classes (.is-empty, .has-content).
  • Manipulate nodes with JS to control when an element should be considered "empty."

FAQ

  • Do spaces count as content?
    • Yes, a single space disqualifies it from :empty.
  • Do HTML comments affect it?
    • Yes. A comment is a node → the element is no longer empty.
  • Can I combine :empty with ::before?
    • Yes, and it is widely used to display messages in empty elements.
  • Does it work in all modern browsers?
    • Yes, its support is excellent.
  • Is it useful for hiding empty containers?
    • Exactly. It is one of its most common uses.

Conclusion

The :empty pseudo-class is much more useful than it seems. It can help you debug, style, hide, or identify elements without real content. You just have to keep in mind that "empty" truly means empty: no nodes, no text, no spaces. If you understand this well, it will save you time and headaches, especially in projects where the content is not always under your control.

I agree to receive announcements of interest about this Blog.

The selector or pseudo-class :empty allows you to select elements with empty content and apply a style to them. For the selector, the use of :before and/or :after are not content, but children/nodes, comments, etc. are.

| 👤 Andrés Cruz

🇪🇸 En español