Empty States
Empty state patterns for when there's no content to display. State-driven feedback with semantic HTML.
Overview
Empty states show feedback when a container has no content to display. They're a state of the container, not a separate component.
Key concepts:
- Use
data-state="empty"on the container - Use
<output data-empty data-feedback="message" role="status">for semantic, accessible feedback - The
<output>element is the correct semantic choice — it represents the result of an action (query returned 0 items) - Mark populated content with
.contentclass - CSS shows/hides content based on state attribute
- Works without JavaScript (progressive enhancement)
See also: Feedback States for the unified pattern covering empty, loading, and error states.
The Pattern
An empty state is fundamentally feedback about a container's current status. The pattern uses:
- A container with
data-state="empty"when content is absent - Content marked with
.contentclass that gets hidden via CSS when state is "empty" <output data-empty data-feedback="message" role="status">to show the feedback
Simple Example
A minimal empty state with an icon, heading, and description. The container shows where messages would appear, with feedback when none exist.
With Action Button
An empty state with a call-to-action button inside the output. Use this when users can immediately add content.
With Illustration
An empty state with space for a custom illustration or image. Use this for feature-level empty states where visual appeal matters.
Semantic Elements
Use appropriate elements within the output for each content type:
| Content Type | Element | Purpose |
|---|---|---|
| Status message | <output role="status"> |
Semantic result of an action, announced by screen readers |
| Heading | <h3> or appropriate level |
Describes the empty state |
| Description | <p> |
Explains what will appear or why it's empty |
| Action | <button> or <a> |
Optional CTA to add content |
Accessibility
<output>element: Represents the result of an action. Screen readers announce its content naturally when it becomes visible.role="status": Creates a polite live region. When the empty state appears via JavaScript, screen readers announce the message without interrupting..visually-hiddenheadings: Container headings like<h2 class="visually-hidden">Messages</h2>provide navigation landmarks for screen reader users even when hidden visually.- Decorative icons:
<icon-wc>without alabelattribute is automaticallyaria-hidden="true", preventing redundant announcements alongside the heading text.
JavaScript Integration
The pattern works CSS-only with server-rendered data-state="empty". For dynamic content, toggle the attribute:
Icon Options
Choose icons that represent the empty content type. Common icons from the Lucide set:
| Icon | Name | Use For |
|---|---|---|
inbox |
Messages, notifications | |
file-text |
Documents, notes | |
users |
People, team members | |
folder |
Files, projects | |
search |
Search results | |
image |
Photos, media | |
calendar |
Events, schedules | |
shopping-cart |
Cart, orders |
Usage Notes
- Be helpful: Explain why the area is empty and what content will appear there
- Provide actions: When possible, include a button or link to add content
- Keep it brief: Use short, clear messages that don't overwhelm
- Match the context: Use icons and illustrations that relate to the content type
- Consider states: Differentiate between "no content yet" and "no results found"
Related
Feedback States
Unified empty, loading, and error states
Error Pages
404, 500, and maintenance pages
Skeleton
Loading placeholders for content