CSS :empty Pseudo-Class

The CSS :empty pseudo-class selects elements that have no child elements or text content. It is useful for hiding empty containers, styling placeholders, and identifying elements that have not received content. Whitespace handling is important because current browser implementations generally treat spaces and line breaks as content.

:empty Syntax

:empty {
  property: value;
}

The :empty pseudo-class does not accept arguments. It can be combined with an element selector, class selector, or other selectors to target particular elements without child content.

Example Syntax

div:empty {
  display: none;
}

This rule hides <div> elements that have no child nodes that prevent them from matching :empty.

The :empty pseudo-class has a specificity of 0-1-0. Combined with the div type selector, its specificity becomes 0-1-1.

How :empty Works

The :empty pseudo-class examines an element's child nodes to determine whether the element is empty.

In current browser implementations, an element matches :empty when it contains no child elements or text nodes. Comments and processing instructions do not prevent matching.

A text node containing only spaces, tabs, or line breaks generally prevents an element from matching :empty in current browsers.

Expected Matching Behavior

Element Content Matches :empty?
No child nodes Yes
HTML comment only Yes
Text content No
Whitespace-only text node No in current browser implementations
Child element No
Child element that is hidden with CSS No
Only CSS-generated content Yes, if no actual child content exists

The browser automatically updates :empty matching when JavaScript adds or removes child content.

Important: The :empty pseudo-class examines document content, not whether an element looks empty on the screen. Hidden elements and invisible text still count as content.

Elements That Match :empty

The :empty pseudo-class can match any element that satisfies its empty-content condition. It is not limited to particular HTML elements.

HTML Examples

HTML Matches?
<div></div> Yes
<p></p> Yes
<div><!-- Comment --></div> Yes
<p>Hello</p> No
<div><span></span></div> No
<div> </div> No in current browsers

Empty Paragraph

<p></p>
p:empty {
  display: none;
}

The paragraph has no child content, so it matches :empty and is hidden.

Element Containing a Comment

<div><!-- Content will be added later --></div>

The comment does not count as child content for :empty matching, so the element still matches.

Element Containing a Child Element

<div><span></span></div>

The outer <div> does not match :empty because it contains a <span> child. The <span> itself does match because it contains no child content.

Void Elements

<img src="image.jpg" alt="Example image">
<input type="text">

Void elements such as <img> and <input> cannot have child content in HTML and therefore match :empty. Avoid using an unrestricted :empty rule to hide elements across an entire page.

Whitespace Behavior

Whitespace is one of the most important details when working with :empty.

Although the Selectors Level 4 specification defines :empty to ignore document whitespace, current browser implementations generally follow the older behavior, where whitespace text nodes prevent matching.

No Whitespace

<div class="message"></div>

This element matches :empty because it has no child content.

Whitespace Between Tags

<div class="message">
</div>

The line break between the opening and closing tags creates a whitespace text node. In current browsers, this generally prevents the element from matching :empty.

Spaces Inside an Element

<div class="message">   </div>

The spaces create a text node, so the element does not match :empty under current browser behavior.

CSS-Generated Content

<div class="message"></div>
.message:empty::before {
  content: "No messages available.";
  color: #777;
}

The generated text appears visually, but it does not create a child text node in the document. The element continues to match :empty.

Note: Do not rely on CSS-generated content alone for important information that must be reliably available to assistive technologies.

:empty vs. :blank

The :empty and :blank pseudo-classes are related, but their intended matching conditions differ.

Pseudo-Class Matching Behavior
:empty Matches elements without child elements or relevant text content. Current browsers generally count whitespace text nodes as content.
:blank Intended to match empty elements and elements containing only document whitespace.

The :blank pseudo-class is experimental and does not have broad browser support. The current Selectors Level 4 definition of :empty also includes whitespace-only elements, but that behavior has not been widely implemented.

Example

<div class="message">   </div>
.message:empty {
  display: none;
}
.message:blank {
  display: none;
}

In current browsers, the whitespace generally prevents :empty from matching. The :blank rule is intended to handle whitespace-only content, but cannot be relied upon without browser support.

For reliable behavior today, remove unwanted whitespace text nodes or use JavaScript to check whether an element contains meaningful content.

Practical Uses

The :empty pseudo-class is useful for interfaces where containers may not always contain content.

Hiding Empty Containers

.notification:empty {
  display: none;
}

This rule hides notification containers that have no child content.

Displaying Placeholder Text

.result-box:empty::before {
  content: "No results available.";
  color: #777;
  font-style: italic;
}

This rule displays a visual placeholder when the result container is empty. For important status messages, use actual HTML content instead of relying only on a pseudo-element.

Removing Empty Paragraph Spacing

article p:empty {
  display: none;
}

This rule prevents completely empty paragraphs from occupying layout space. Paragraphs containing whitespace text nodes may still occupy space in current browsers.

Styling Empty List Containers

.item-list:empty {
  display: none;
}

An empty list can be hidden until JavaScript adds list items. Avoid leaving whitespace between the list's opening and closing tags when using this approach.

Identifying Empty Content Areas

.content-area:empty {
  min-height: 60px;
  border: 2px dashed #ccc;
  background-color: #f8f9fa;
}

This rule provides a visible placeholder area when a content container has no children.

Best Practices

  • Use :empty when an element should be styled according to whether it contains child content.
  • Remember that whitespace text nodes generally prevent matching in current browsers.
  • Keep opening and closing tags together when you need an initially empty HTML container.
  • Use specific selectors such as .notification:empty rather than applying :empty globally.
  • Remember that comments do not prevent an element from matching :empty.
  • Remember that hidden child elements still prevent their parent from matching :empty.
  • Use JavaScript when you need to distinguish meaningful text from whitespace reliably.
  • Do not use :empty to determine whether a form input has a value. Use appropriate form-related pseudo-classes or JavaScript instead.
  • Do not rely on CSS-generated placeholder text for essential information.
  • Test dynamically updated content to confirm that styles change when children are added or removed.

:empty Example

This example demonstrates how :empty responds when JavaScript adds or removes content. An empty message container displays a placeholder. Click Add Message to insert text, then Clear Message to remove it.

HTML

<div class="empty-demo">
  <div class="message-box" id="message-box"></div>
  <button type="button" id="add-message">Add Message</button>
  <button type="button" id="clear-message">Clear Message</button>
</div>

CSS

.empty-demo .message-box {
  min-height: 50px;
  padding: 12px;
  margin-bottom: 12px;
  border: 2px solid #0088cc;
  background-color: #eaf6fc;
}
.empty-demo .message-box:empty {
  border: 2px dashed #999;
  background-color: #f5f5f5;
}
.empty-demo .message-box:empty::before {
  content: "No message available.";
  color: #777;
  font-style: italic;
}
.empty-demo button {
  padding: 7px 10px;
  margin: 0 4px 5px 0;
  cursor: pointer;
}

JavaScript

const messageBox = document.querySelector("#message-box");
document.querySelector("#add-message").addEventListener("click", () => {
  messageBox.textContent = "Your message has been added.";
});
document.querySelector("#clear-message").addEventListener("click", () => {
  messageBox.textContent = "";
});

Browser Result

The empty container initially displays a dashed border and placeholder text. Adding a message changes its appearance. Clearing the message restores the empty-state styling.

Play in Editor

Browser Support

Baseline: Widely available. The :empty pseudo-class has been supported across major browser engines for many years and works in modern versions of Chrome, Edge, Firefox, Safari, and other browsers.

Current browser implementations generally require an element to contain no child elements or text nodes. The newer Selectors Level 4 definition also allows whitespace-only text, but that behavior is not yet consistently supported.

For current compatibility information, visit Can I Use? .

Specifications

The :empty pseudo-class is defined in Selectors Level 4. Its original matching behavior was defined in Selectors Level 3.

Selectors Level 4 - The :empty Pseudo-Class

Selectors Level 3 - The :empty Pseudo-Class