Understanding CSS :blank vs :empty Pseudo-Classes

The CSS :blank pseudo-class is a Selectors Level 4 proposal designed to target elements that contain no content or contain only whitespace. While modern web design frequently requires hiding or styling elements without visible content, the traditional :empty selector has strict limitations that make this difficult. This article explains the :blank proposal, outlines how it functions, and details the key differences between :blank and :empty.

What is the :empty Pseudo-Class?

The :empty pseudo-class has been part of the CSS specification since CSS2 and was updated in Selectors Level 3. It targets any element that has no child nodes whatsoever.

For an element to match :empty, it cannot contain:

  • Child elements (such as <span> or <p>)
  • Text nodes
  • Entity references

The major limitation of :empty is how it handles whitespace. In HTML, a space, tab, or newline character creates a text node in the Document Object Model (DOM). Consequently, an element formatted across multiple lines or generated with trailing whitespace by a template engine is not considered empty:

<!-- Matches :empty -->
<div class="card"></div>

<!-- Does NOT match :empty due to the space -->
<div class="card"> </div>

<!-- Does NOT match :empty due to newlines/tabs -->
<div class="card">
</div>

Because of this strict definition, developers often have to strip all whitespace between tags in their HTML or use JavaScript to conditionally remove unused containers.

What is the Proposed :blank Pseudo-Class?

The :blank pseudo-class was introduced in the CSS Selectors Level 4 specification to solve the whitespace limitation. It provides a more forgiving and practical definition of an "empty" element.

Under the proposal, :blank matches:

  1. Elements that have no child nodes at all.
  2. Elements that contain only whitespace characters (spaces, tabs, newlines).

With :blank, code formatting no longer breaks CSS styling logic:

<!-- Both match :blank -->
<div class="alert"></div>

<div class="alert">
    
</div>

Form Input Handling

Early iterations of the Selectors Level 4 draft also proposed that :blank could apply to form control elements, such as <input> and <textarea>, matching them when their user-entered value is empty.

Because void elements like <input> never have child elements, :empty cannot detect whether an input contains text. While :placeholder-shown is commonly used as a workaround to detect empty inputs today, :placeholder-shown fails if an input does not have a placeholder attribute defined. The form-handling capability of :blank was designed to solve this gap.

Key Differences Between :blank and :empty

Feature :empty :blank
Whitespace Handling Treats whitespace as content; does not match if spaces or newlines exist. Ignores whitespace; matches elements containing only spaces, tabs, or newlines.
Sensitivity to HTML Formatting High. Line breaks and indentation break the selector. Low. Allows clean, indented HTML structure.
Form Controls Only checks DOM children; cannot detect user input in form fields. Designed to match form controls that have empty input values.
Specification Status Stable and fully supported across all modern browsers. Candidate Recommendation (Selectors Level 4); limited native browser implementation.

Current Implementation Status

While :empty is fully supported across all browsers, :blank has faced slow adoption and implementation delays. Browser engines have debated implementation details, specifically around performance implications of traversing whitespace text nodes and how the selector should interact with form controls versus standard containers.

Until :blank achieves broad cross-browser availability, developers relying on empty state styling typically use :empty with minified HTML, the :has() selector (e.g., :not(:has(*))), or :placeholder-shown for text inputs.