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 .content class
  • 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:

  1. A container with data-state="empty" when content is absent
  2. Content marked with .content class that gets hidden via CSS when state is "empty"
  3. <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-hidden headings: 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 a label attribute is automatically aria-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