Distinguish the reason
A newly created workspace should explain how its first record arrives. A filtered list should retain the active filters and offer a way to change them. A failed request should report the failure rather than implying that the underlying records disappeared.
Decide these states alongside the normal populated screen. Waiting until implementation is nearly finished often produces a single generic message that does not match the different situations.
Offer one relevant action
The best next step depends on the user’s responsibility. Someone allowed to create records may need a creation button. A viewer may need to know who supplies the information or when it becomes available.
Avoid offering an action the person cannot complete. If access is the issue, explain the appropriate route to request it without revealing information they should not see. If the system is waiting on an external process, explain that dependency in language the user understands.
Preserve context
Keep the page title, navigation, and useful controls in place. An empty result should not feel like an unrelated error page. For search results, show the query that produced the result so someone can revise it confidently.
Test the state with the same care as a populated table. Check keyboard navigation, narrow screens, and what happens when the first record appears. If the page refreshes automatically, make the transition understandable and avoid moving focus away from the person’s current action.
A good empty state answers three questions: why there is nothing to show, whether that is expected, and what the person can do next. It does not need a long explanation or a decorative illustration to be useful.
Model the states before writing the message.
An empty area is a visual symptom, not a diagnosis. Ask whether the application successfully loaded an empty collection, filtered a nonempty collection to zero, or failed to determine its contents. Those conditions should be represented separately in the application state.
| State | Useful message | Next action |
|---|---|---|
| New workspace | No projects have been created in this workspace. | Create a project, if permitted. |
| Filtered to zero | No projects match the current filters. | Show and clear the active filters. |
| Access restricted | Your account does not have access to this area. | Use the established access-request route. |
| Load failed | The project list could not be loaded. | Retry without implying that records were deleted. |
The sample copy is intentionally specific about what the application knows. It does not promise that data is safe when the outcome is uncertain, and it does not invite a user to create a project merely because loading the existing projects failed. A create action belongs to the workspace’s permissions, not to its visual emptiness.
Make changing results understandable.
When filters change results without a page navigation, update a concise result message. W3C’s explanation of status messages describes how such information can be made available to assistive technology without moving focus unnecessarily.
<p id="result-count" role="status" aria-atomic="true">
No projects match your filters.
</p>
<button type="button">Clear filters</button>This fragment is only the presentation layer. The reset action must also clear the actual filter state, refresh the results, and keep the URL consistent if filters are shareable. Test browser back navigation and a bookmarked zero-result search; otherwise the visible controls can disagree with the query being executed.
Include every state in interface review, not just the first-run screenshot. Try removing the last matching record, losing access while a view is open, and receiving an error during refresh. Decide whether previously loaded information remains visible and how its freshness is communicated. A calm empty state is useful only when it does not conceal stale or failed data.
A practical example.
A project list can be empty because a new account has no projects, because a filter excludes every project, or because the user lacks access. Those conditions need different messages and actions. “Nothing here” does not help someone distinguish them.
For a new account, explain the object and offer the first permitted action. For a filtered list, show the active filters and provide a reset. For an access issue, describe the appropriate route to an administrator without implying that hidden records do not exist. Also test a failed data load separately: it should not look like a successful empty result. Keeping these states distinct prevents users from creating duplicates or assuming their records have disappeared.
Put it into practice.
- Distinguish a new workspace, an empty search, a permission limit, and a loading failure.
- Offer one relevant action instead of generic motivational copy.
- Avoid showing a create action to someone who cannot complete it.