Blog

Empty, Loading and Error States in Product Design

A robust user flow defines more than the ideal screen with all data in place. It also covers first use, empty results, loading, partial data, errors and success. If those states are missing from the design file, the product will still display them—but the browser, operating system or a developer under deadline will decide how.

Published: Written by: Kağan Giray Eroğlu

Why is the ideal screen not enough?

A meaningful share of an interface's real life is spent outside its ideal state. Connections slow down, searches return nothing, a new user has not created data yet, or a service request fails. Designing only the populated screen leaves the most fragile moments of the experience undefined.

A screen state is not decoration; it is behavior. The flow is not complete until its states are defined.

The 6 states every flow should cover

StateThe user's questionThe design's answer
First useWhat do I do here?A short explanation and one starting action
LoadingIs the system working?Feedback appropriate to the duration
Empty resultWhy is nothing here?The reason and, where possible, a next step
Partial dataWhat is missing?Keep available content and mark the missing part locally
ErrorWhat happened and what can I do?A clear reason, retry action or alternative path
SuccessDid it work?Confirmation and the next logical action

An empty state is more than an empty box

An empty state can have two very different causes: the user has not created anything yet, or their filters and search returned no results. The first should help them add content; the second should help them clear a filter or change the query. Reusing the same illustration and copy for both hides the cause of the problem.

  • Explain why the state is empty in one sentence.
  • Offer one primary action the user can take.
  • If no action is possible, explain the expectation instead of adding a false button.
  • Separate search and filter emptiness from first-use emptiness.

Choose loading feedback by duration

The same loading indicator should not be used for every wait. On very short operations it can create a visual flash; when the content structure is known, a skeleton prevents layout shift; beyond a few seconds, users need to know that work continues and whether they can leave the screen.

Estimated durationSuitable approachAvoid
0-300 msUsually show no indicatorA brief visual flash
300 ms-2 secSkeleton or local indicatorLocking the whole screen unnecessarily
2-10 secClear status copy and progress feedbackAn ambiguous endless spinner
10 sec +Background task, notification or real progressMaking users wait without context

An error message should answer three questions

  1. What happened? State the outcome for the user instead of leading with a technical code.
  2. Is my data safe? Do not leave it unclear whether the operation completed.
  3. What can I do now? Provide a retry, correction or support path.

An error that does not concern the whole screen should not block the whole screen. If a profile photo fails to load, keeping the remaining profile visible and showing the error in the photo area gives the user a better recovery path.

A development-ready design handoff

Delivering one ideal screen in Figma defers behavior decisions to development. Every critical screen needs a state matrix that defines its content, action, component variant and transition rule in one place.

  • Component variants: default, focus, disabled, loading, error and success
  • Realistic sample content and overflow scenarios
  • Responsive behavior for mobile and desktop
  • A clickable prototype showing transitions between screens
  • Notes distinguishing local errors from page-level errors

Frequently asked questions

What is an empty state?

An empty state explains why a screen has no data to show and, where possible, offers a next step. First use, an empty search result and content hidden by permissions are different states and need different messages and actions.

Should I use a skeleton screen or a spinner?

When the content layout is known and the wait is longer than roughly 300 milliseconds, a skeleton can reduce layout shift. A spinner can work for small local actions. Longer operations need context or real progress rather than a spinner alone.

How do you write a good error message?

A good error message describes what happened in user language, makes the status of the operation or data clear, and offers an actionable next step such as retrying, correcting input or contacting support. Technical codes should be secondary information.

Which states belong in a design file?

Every critical flow should include at least first use, loading, empty result, partial data, error and success. Interactive components should also define default, focus, pressed and disabled variants.

Let's start your project together

Fill in the short form and we'll get back to you within 12 hours. Every project gets a tailored solution.

Get in touch