Empty State Design: Where the Screen Loses the User
An empty app screen is almost always read by the user as a malfunction, not as “there is no data yet.” If after launch they see a white field without explanations, the decision is made in a couple of seconds: the app is broken, I need to reinstall it or go to another one. This is exactly where the user is lost at the start — before they reach the product’s value.
There are four situations where a screen without data looks the same but requires a different solution: an empty list (the first object has not yet been created), a filter or search result (data exists, but it did not match the conditions), no history for a period, and the first login to the app, when records physically cannot exist.
Empty state design begins with a state model, not with a picture. The screen is described in four modes: loading, empty, error, data. Empty is a successful server response with zero records; error is a request that did not arrive or was rejected.
If they are not separated, when the connection drops a person sees “list is empty,” decides the data has been deleted, and leaves.
Next is skeleton layout during loading, so there is no flashing emptiness, and contextual text with one meaningful action: create the first object, reset the filter, retry the request. Offline, we serve cache with an age marker.
The control metric is the share of sessions where the target action was performed after the empty state: it shows whether we explained the screen or just decorated it.
What Screen Refinement Delivers: Measurable Results
Empty screen work is evaluated not by mockups but by behavior: the share of sessions interrupted on the first screen, the number of steps to the first useful action, and the composition of support requests on the topic “opened it — and it’s unclear what to do.” Measurements are taken before and after the changes — the difference is the result.
Abandoned sessions at the start are the most expensive area. A user who opens an app for the first time with an empty list, without a hint, leaves in the first seconds and often does not return.
A clear next step on the screen returns some of these sessions to work on the very first visit, not on the conditional third one.
Support load is calculated by request topics. Questions like “it’s empty and unclear” are typical, and they are closed by the text on the screen, not by an operator.
When the state itself explains the situation and offers an action, the flow of identical requests decreases, and team time goes to complex cases.
The path to the first action is a metric that shows the effect of short text and a button. The empty state is the only point where the app can guide the user by the hand; without it, the path gets longer by searching, and some people do not reach the result.
To keep the result stable, the rules are fixed once — in components, wording, and screen behavior according to Material Design. Then a new screen inherits a proven solution, and metrics do not diverge from build to build.
Approaches to Screen Design: Comparison Table
When an app consists of dozens of screens, and every list, filter, search, and history has an empty state, the question is not whether to draw it, but how to organize work on it.
In practice, we use three schemes — from fast to most precise — and choose the scheme for the product’s maturity, not the designer’s taste.
| Work option | When it fits | Limitations |
|---|---|---|
| Ready-made state templates — a library of typical solutions: no data, no search results, loading error, no access | Early product stages, same-type sections, need a quick result across the whole app | Texts and actions are universal — in complex scenarios the hint does not fit the user’s context |
| Scenario-based design — the state is drawn for a specific path: why the screen is empty, what the person did before, which one action will return them to the flow | Key funnels: first login, payment, content loading, onboarding tasks | More time-expensive, requires describing scenarios before work begins |
| Hybrid approach — base states are taken from the library, significant screens are refined for the scenario | Most mature apps: savings on typical screens, precision on critical ones | Discipline is needed: rules for when a template can remain and when refinement is mandatory |
The comparison of work options shows the main trade-off: templates give speed and consistency, scenario-based design gives conversion at important steps.
The hybrid removes the extremes, but works only with fixed selection rules — otherwise the library degrades into a set of heterogeneous screens.
Work Stages: From Screen Inventory to Handoff
An empty state is a branch of the scenario that the user goes through before the main content, not a placeholder with an icon. While there are dozens of screens, states sprawl: somewhere there is two-word text, somewhere a button leads to a dead end.
We work in stages — this way, by release, every branch has text, an action, a mockup, and an acceptance criterion.
- Screen inventory. For each screen, we record states: first launch, empty after filter, no results, network error, permission denied, loading. The result is a summary table, shared by design and the backlog.
- State prioritization. We sort branches by frequency and cost of error: everyone sees an empty list after a filter, few see access denial — but it breaks the scenario entirely. We close first what breaks the main path.
- Behavior schemes. We describe what the user sees, where the main action leads, and how many steps to the first content; we decide where a hint is enough and where training is needed.
- Text approval. Tone, length for wrapping, form of address, localization, and right-to-left scripts — we coordinate with product and support. The text explains the reason, not just states emptiness.
- Mockups. One set of components: light and dark theme, large system font, long names, skeletons instead of an indicator. We define icons and illustrations with tokens so a new screen is not drawn from scratch.
- Testing on real data. We run mockups on live responses: an almost empty list, truncated headings, an error without network, first launch on a clean device. This surfaces branches that look working on demo data.
- Handoff to development. State map, display rules, texts, tokens, and acceptance criteria: the developer sees when the state turns on, the tester sees what counts as a defect.
Deliverables: Mockups, Descriptions, and Screen Rules
The deliverable set is not a collection of images but a working package that a developer uses to assemble the screen without additional questions for the designer.
An empty state is rarely just one: one screen has five or six of them, and each requires a separate mockup and a separate behavior rule. Below is what remains with the client’s team after handoff.
- Mockups of all variants: first launch, empty after data deletion, no search results, loading failure, no network, no access rights — in compact and full layout.
- Screen behavior rules: what is shown when data returns, how the refresh button works, whether the hint repeats after a failure and after what time loading transitions to the error state.
- Text table: string identifier, wording for each state, length limit, translation notes. Texts live separately from mockups — editing a phrase does not require rebuilding mockups.
- Transition scheme: from which state and by which action the user goes where, including going back and workaround paths.
- Screen specifications: spacing and block sizes, behavior at different screen sizes and enlarged system font, light and dark themes.
- Documentation for developers: mapping states to interface components, button and field states, what to show with partially loaded data.
- Acceptance checklist: scenarios used to test the implementation — network drop, empty response, slow response, re-entry.
We hand over each item in source files and as an assembled description, so the rules can be read without opening the mockups. The client’s team can give the package to a new contractor and get the same screen, not their own loose interpretation of it.
Case Study: How We Reduced First-Launch Drop-offs
An app with deferred registration: a person builds an order and browses the catalog without an account; login is requested only before payment.
Before the changes, all empty states — “Favorites,” “My Orders,” “Addresses,” search results — looked the same: a white screen, a gray icon, and the caption “Empty for now.” First-launch drop-offs held at 58%, 23% reached the first target action, and 16% returned on the third day.
What Was Changed in Screen Behavior
We separated three states that previously looked like one: “no data yet,” “no network,” and “request failed.” Each received its own text, understandable without technical details, and one target action — choose a product, retry the request, enter the address manually.
Instead of emptiness during loading, row skeletons are shown, so the screen does not look broken even on a slow connection.
Cart and favorites drafts are written locally before registration and synchronized after login — the scenario “built an order, registered, everything disappeared” is removed. Texts and button composition are switched by Firebase Remote Config without releasing a new build.
A month after release: first-launch drop-offs — 58% → 31%, reaching the first target action — 23% → 49%, third-day returns — 16% → 29%. Support requests “data disappeared” dropped by a factor of three — separating error and empty states produced the effect.
How Does the “No Data” State Differ from a Loading Error?
The difference between states is in the cause, not in the design. An empty response means the request ran and returned a zero set: there is no data yet, the screen explains why and leads to the target action. A loading error is a failure in which data may exist, but it could not be delivered.
Loading is in progress — the third scenario: the container is already rendered, but the response has not arrived yet. If we show emptiness text here, we will make the user read “no orders” before the response and leave.
Therefore the skeleton, text, and button are separate layers with different display conditions. It is convenient to check state separation against Material Design.
| State | Text | Action | Retry |
|---|---|---|---|
| No data yet | “Empty for now” | Create the first record | Not needed |
| Nothing by filter | “Nothing found” | Reset filter | Not needed |
| Loading in progress | Skeleton, without text | None | Automatic, once |
| Loading error | “Failed to load” | Retry | By button, with pause |
| No rights | “No access” | Switch account | Not needed |
Retry is the main marker of difference. The retry button exists only for a failure; for emptiness, the target action is used instead, otherwise the user endlessly refreshes a screen where there is nothing to refresh.
Automatic retry after an error goes with increasing pause and a limited number of times, and when there is no network, the text changes to “no connection”: retry is meaningless until the connection returns.
In the design system, the difference is fixed by a state catalog: for each one, the entry condition, text, action, and behavior upon returning to the screen are specified.
The developer connects a ready-made set instead of strings in the markup — states do not mix between releases, and support stops sorting through “orders disappeared” requests.
Technical Doubts: Analyzing Complex Cases
An empty state is the hardest to catch: on a staging environment with demo data it is invisible, and in production the screen flashes between the server response and rendering.
Therefore we keep a source switch — it substitutes an empty response, an error, access denial, and long loading — and run the build through all scenarios before release.
A separate question is texts and the number of variants. The product side is responsible for wording, while the designer and our engineers are responsible for behavior on narrow screens: we fix roles in advance so edits do not slow down the build. For one state, we make one or two variants — more is support load without noticeable return.
How do you test empty screens if the staging environment always has data?
We switch the source to sets with empty responses and errors and add response delay to catch the loading state. We take reference images on small and large screens — layout discrepancies are visible before deployment.
What should we do if the app is already released?
We make targeted edits: texts, hints, and illustrations are changed without rewriting the logic and are shipped in the next update. Behavior changes are covered by a switch, so the previous variant remains available for a quick rollback.
Who is responsible for screen texts?
Wording is approved by the product side; we are responsible for how they look in the interface: line length, wrapping, button states. If the text arrives later, the screen is assembled with a placeholder substitution and does not block work.
Let’s Discuss the Task: Audit and Plan for Your App
To make the conversation concrete, before the meeting a test build and a list of screens where data comes from outside are enough: lists, profile, feed, search with filters.
On the call, we analyze how the app behaves in four situations — no data yet, loading in progress, request failed, no network — and where the state is simply not described, so the user sees a white screen.
After the screen audit, we return with specifics:
- a map of screens with asynchronous data and a state matrix: empty, loading, error, offline, no access;
- a list of places where the empty state substitutes for an error or a stuck loading;
- scope of work: which states we design, which texts and hints we write for them, what we reuse from current components;
- a work plan with the order of releasing screens to production and dependencies on backend contracts;
- timeline estimate by stages — design separately, handoff to development and testing on the build separately;
- an acceptance checklist: by what signs we consider a state ready, and not just “drawn”;
- agreement on the next step — who sends what and by what date.
Describe the task and attach what you have: mockups, screenshots of problematic screens, access to the test build. We will return with an assessment and work plan — without generic words about “improving the experience.”







