Three quick rules for empty states
Empty is not blank. It is an opportunity.
Empty states are easy to underestimate because they look like small copy problems. A table has no rows. A search has no results. A dashboard has no data yet. Write a friendly sentence, add an illustration, and move on.
That misses the point. An empty state is a product decision point. It is the moment where the user discovers that the product cannot show what they expected. Your job is to explain why, preserve confidence, and give them a useful next move.
Rule 1: Say what happened
The first sentence should explain the state in plain language. Avoid cute copy until the user understands the situation.
Weak:
Nothing to see here.
Better:
No invoices match those filters.
The second version gives the user a reason. It also hints at the fix: change the filters.
Different empty states need different explanations. "No projects yet" is not the same as "No search results" or "No data because the integration is disconnected." If those states share one generic component, the product will feel vague at exactly the moment clarity matters.
Rule 2: Match the tone to the stakes
Empty states are often overdesigned. A playful illustration can work for an onboarding checklist. It can feel absurd when the user is looking for a failed payment, a missing patient record, or a production alert.
Tone should follow consequence:
- Low stakes: friendly, light, optionally illustrative.
- Medium stakes: direct, specific, action-oriented.
- High stakes: calm, precise, and careful with blame.
The product should not sound excited that the user has no data. It should sound useful.
Rule 3: Offer one next action
Many empty states fail by offering too many paths. Import data, create a record, invite a teammate, read docs, watch a video, contact support. That may feel helpful internally, but it forces the user to decide before they understand the problem.
Pick the most likely next action and make it primary. Put secondary actions in quieter links if they are truly useful.
For example:
- Empty project list: Create project.
- Empty filtered table: Clear filters.
- Disconnected analytics: Connect data source.
- Empty notification inbox: Explain that new alerts will appear here.
The action should match the cause. Do not ask someone to create a new invoice when the real issue is that the current filter hides invoices.
Design the state before the component
It is tempting to build one EmptyState component with title, body, image, and action props. That component is useful, but the product thinking has to happen first.
Before designing the component, define the state taxonomy:
- Onboarding empty: nothing exists because the user has not started.
- Permission empty: something exists, but this user cannot see it.
- Filtered empty: something may exist, but the current query hides it.
- System empty: data cannot load because an integration, network, or backend path failed.
- Success empty: nothing appears because everything is handled.
Each state needs different copy, action, and sometimes different visual weight.
Explain the first object and offer creation.
Show what constrained the results and clear it.
Name the dependency and route to retry or support.
A small copy checklist
When reviewing an empty state, I use five questions:
- Does the user know why this area is empty?
- Does the copy avoid blaming the user?
- Is the next action obvious?
- Is the tone proportional to the stakes?
- Would this still make sense without the illustration?
That last question is important. Illustrations can support an empty state, but they cannot carry the explanation. If the copy fails without the image, the state is not done.
The best empty states create trust
Empty states are not edge cases. They are common first impressions. New users see them during setup. Returning users see them when filters are too narrow. Admins see them when permissions or integrations are incomplete.
A good empty state says, "The product understands where you are." It makes absence legible. It gives the user a path. It keeps the interface from feeling broken.
Implementation details
A strong empty-state component should support variation without forcing every screen to reinvent layout. I usually want slots or props for title, body, primary action, secondary action, visual, and state type. The state type can drive spacing, visual weight, and default tone.
For example, a filtered empty state can be compact and appear inside a table body. An onboarding empty state may deserve more space, a stronger visual, and a primary creation action. A system error should include retry behavior and may need a support path.
The component should also avoid layout shift. If a table changes from loading to empty to populated, the surrounding shell should remain stable. Users read stability as reliability.
What to avoid
Avoid vague humor. Avoid blaming the user. Avoid telling people to "try again later" without saying what failed. Avoid illustrations that make serious workflows feel childish. Avoid generic empty copy that appears in five unrelated contexts.
Most of all, avoid hiding the reason. A user who understands why something is empty can decide what to do next. A user who only sees a friendly blank state has to guess.
That is why empty is not blank. Empty is a moment of guidance.