CSS :empty Selector

Beginner
⏱️ 5 min read
📚 Updated: Jul 2026
🎯 4 Examples
Structural States

What You’ll Learn

The :empty pseudo-class targets elements that contain no child elements and no text. It is useful for highlighting blank containers, handling dynamic content gaps, and building cleaner layouts.

01

No children

Zero content.

02

No text

Includes spaces.

03

Any element

div, p, li…

04

Placeholders

Empty slots.

05

Layout gaps

Spot blanks.

06

Pitfalls

Whitespace.

Introduction

The :empty selector in CSS is a pseudo-class used to match elements that have no children at all — no element nodes and no text nodes.

It lets you apply styles specifically to completely blank containers, which is helpful when managing layout gaps, styling placeholders, or debugging dynamically generated content.

Definition and Usage

Append :empty to any element selector with no space before the colon: div:empty, p:empty, or .card:empty. Styles apply only while the element remains truly empty.

💡
Beginner Tip

Even a single space between opening and closing tags creates a text node, so <p> </p> is not empty. Write <p></p> with nothing inside for :empty to match.

📝 Syntax

The syntax for the :empty pseudo-class is:

syntax.css
element:empty {
  /* CSS properties */
}

Basic Example

empty-basic.css
:empty {
  border: 2px dashed #ef4444;
  background-color: #fef2f2;
  min-height: 3rem;
}
div:empty p:empty .card:empty li:empty

Syntax Rules

  • An element matches only when it has zero child elements and zero text nodes.
  • Whitespace (spaces, tabs, line breaks) counts as a text node and prevents a match.
  • HTML comments alone do not prevent :empty from matching in modern browsers.
  • Self-closing elements like <br> or <img> inside a container mean it is not empty.
  • Combine with classes for scoped styling: .message:empty.

Related Selectors

  • :blank — matches elements with no content or only whitespace (limited browser support)
  • :not(:empty) — targets elements that do contain children or text
  • :has() — parent selector; useful for styling containers based on child content
  • ::before / ::after — add placeholder text to empty elements with generated content

⚡ Quick Reference

QuestionAnswer
Selector typePseudo-class
When it appliesElement has no element children and no text nodes
WhitespacePrevents match (counts as text)
HTML comments onlyStill matches :empty
Common targetsdiv, p, li, span, td
Browser supportAll modern browsers (CSS3+)

When to Use :empty

:empty shines when you need to react to blank markup:

  • Dynamic lists — Highlight or hide list items that JavaScript has not yet populated.
  • Placeholder styling — Show a dashed border or minimum height on empty message boxes.
  • Layout debugging — Visually spot containers that should contain content but do not.
  • CMS content — Style optional content areas that may be left blank by editors.
  • Form feedback — Style error or hint containers before validation messages are inserted.

👀 Live Preview

Filled slots get a green background. Empty slots match :empty and show a dashed red border:

p.slot (has text)

This paragraph has content.

p.slot (empty)

div.slot (empty)

Examples Gallery

Practice :empty with basic highlighting, scoped selectors, dynamic placeholders, and hiding blank containers.

📜 Core Patterns

Style any element that has no children or text content.

Example 1 — Highlight all empty elements

Apply a dashed border and light background to every empty element on the page.

empty-highlight.html
<style>
  :empty {
    border: 2px dashed #ef4444;
    background-color: #fef2f2;
    min-height: 3rem;
  }

  .container p {
    padding: 0.65rem;
    background-color: #ecfdf5;
  }
</style>

<div class="container">
  <p>This paragraph has content.</p>
  <p></p>
  <div class="box"></div>
</div>
Try It Yourself

How It Works

The filled paragraph keeps its green background. The empty <p> and <div> match :empty and receive the dashed red styling.

Example 2 — Scope to a specific class

Target only empty message containers instead of every empty element on the page.

empty-scoped.css
.message:empty {
  display: block;
  padding: 1rem;
  border: 1px dashed #94a3b8;
  border-radius: 0.5rem;
  color: #64748b;
  font-style: italic;
}

.message:empty::before {
  content: "No messages yet.";
}
Try It Yourself

How It Works

Pairing :empty with ::before lets you show placeholder text in a blank container without adding extra HTML.

📄 Practical Patterns

Use :empty for real-world layout and dynamic content scenarios.

Example 3 — Minimum height for empty cards

Prevent collapsed layout when a card body is waiting for JavaScript to inject content.

empty-card.css
.card-body:empty {
  min-height: 6rem;
  background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);
  background-size: 200% 100%;
  border-radius: 0.5rem;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
Try It Yourself

How It Works

While the card body has no content, :empty applies a skeleton loader. Once JavaScript inserts HTML, the rule no longer matches.

Example 4 — Hide empty list items

Remove spacing from list items that have no content in a dynamically built list.

empty-list.css
.todo-list li {
  padding: 0.5rem 0;
  border-bottom: 1px solid #e2e8f0;
}

.todo-list li:empty {
  display: none;
}
Try It Yourself

How It Works

Empty list items are removed from the visual layout. This keeps dynamically generated lists tidy without extra JavaScript checks.

⚠️ Common Pitfalls

  • Whitespace matters<p> </p> contains a space text node and does not match :empty. Remove all characters between tags.
  • Line breaks count — Pretty-printed HTML with a newline inside a tag also creates a text node.
  • Hidden elements still count — A child with display: none or zero size is still a child; the parent is not empty.
  • Self-closing tags<img>, <br>, and <input> inside a container prevent :empty from matching.
  • Not the same as :blank — Do not expect :empty to match whitespace-only elements; use :blank where supported instead.

Whitespace Example

empty-whitespace.html
<!-- Does NOT match :empty (space inside) -->
<p> </p>

<!-- DOES match :empty -->
<p></p>

♿ Accessibility

  • Do not hide meaningful empty regions — If an empty container conveys structure, ensure assistive technology users still understand the layout.
  • Placeholder text via CSS — Content added with ::before may not always be announced by screen readers; prefer real text when the message is important.
  • Loading states — Pair skeleton loaders with aria-busy="true" on the container so users know content is loading.
  • Do not rely on color alone — Combine dashed borders with labels or text when empty states need to be understood clearly.

🧠 How :empty Works

1

Browser inspects the DOM

For each candidate element, the browser checks its child nodes.

DOM
2

Counts element and text nodes

Any element child or text node (even one space) means the element is not empty.

Match test
3

:empty styles apply

If zero children are found, your :empty rules take effect.

Render
=

Blank containers styled

Empty slots are highlighted, hidden, or given placeholders automatically.

🖥 Browser Compatibility

The :empty pseudo-class is supported in all modern browsers. It has been part of CSS since Selectors Level 3 and works reliably across Chrome, Firefox, Safari, Edge, and Opera.

Baseline · Universal support

Structural empty detection everywhere

:empty works in every major browser for layout, placeholders, and debugging blank containers.

99% Universal support
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions
Full support
Opera All modern versions
Full support
:empty pseudo-class 99% supported

Bottom line: :empty is safe for production. For whitespace-only elements, consider :blank where you can accept limited support.

🎉 Conclusion

The :empty pseudo-class gives you a simple, CSS-only way to target elements with no content. It is ideal for placeholders, layout debugging, and cleaning up dynamically generated markup.

Remember that whitespace counts as content, scope your selectors when possible, and pair :empty with ::before for helpful placeholder messages.

💡 Best Practices

✅ Do

  • Scope with classes: .message:empty
  • Write truly empty tags with no whitespace inside
  • Use min-height to reserve space for loading content
  • Combine with ::before for placeholder text
  • Test with dynamically inserted content

❌ Don’t

  • Assume pretty-printed HTML will stay empty
  • Hide empty regions that convey important structure
  • Rely on :empty for whitespace-only elements
  • Forget that child elements prevent a match
  • Use global :empty on large pages without scoping

Key Takeaways

Knowledge Unlocked

Five things to remember about :empty

Use these points when styling blank containers.

5
Core concepts
02

Whitespace

Breaks the match.

Pitfall
💬 03

Placeholders

With ::before.

Pattern
📄 04

Dynamic lists

Hide blank items.

Use case
🌐 05

99% support

All browsers.

Compat

❓ Frequently Asked Questions

The :empty pseudo-class matches elements that have no child elements and no text nodes. It lets you style containers that are completely blank.
Yes. A space, tab, or line break inside an element creates a text node, so the element no longer matches :empty. Write truly empty tags like <p></p> with nothing between them.
No. Comment nodes are not element or text nodes, so an element that contains only <!-- comments --> still matches :empty in modern browsers.
:empty matches only elements with zero children and zero text. :blank (newer, limited support) also matches elements that contain only whitespace.
Yes. All modern browsers support :empty. It has been available since CSS3 and works reliably for layout and placeholder styling.

Practice in the Live Editor

Open the HTML editor and experiment with :empty, whitespace pitfalls, and placeholder styling.

HTML Editor →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful