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:
- Elements that have no child nodes at all.
- 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.