Designing loading states
Three response-time limits
Jakob Nielsen describes three time limits that shape how people experience waiting. They are approximate but useful when deciding what to show.
About 0.1 second
Feels instant. No special feedback is needed.
About 1 second
Keeps the flow of thought. The delay is noticed, but people stay in control.
About 10 seconds
The limit of attention. Beyond it, people turn to other tasks, so show progress and allow cancelling.
These limits describe human perception, not exact thresholds. Treat them as a guide: respond immediately, show that work is happening within a second, and give real progress for anything longer.
Choose the right pattern
- Skeleton screens. Grey placeholders in the shape of the content. They fit page and list loading where the layout is known, and they set expectations about what will appear.
- Spinners. A looping indicator for short waits of unknown length, such as submitting a button action. Avoid them for long waits, because they give no sense of progress.
- Progress bars. Use them when the duration or amount of work is known, such as uploads. They show how much remains and make longer waits easier to accept.
Do not show an indicator for waits under about a second; a brief flash is more distracting than helpful.
Whatever you pick, keep it consistent across the product, and give the loading text a clear subject, for example “Loading messages” rather than only “Loading”.
Content that loads in parts can show each part as soon as it is ready. This is often better than holding everything back until the slowest request finishes, as long as the layout stays stable.
Optimistic UI, time-outs and layout
- Optimistic UI. For actions that almost always succeed, such as liking an item, update the interface at once and confirm in the background. If the request fails, restore the previous state and explain.
- Time-outs and retry. Do not wait forever. After a reasonable time, show a clear message and a “Try again” button, and keep the person’s input.
- Avoid layout shift. Reserve space for content that will arrive, using skeletons of the same size or fixed aspect ratios for images, so nothing jumps when data appears.
Errors deserve their own state. Say what failed in plain words, say whether the person’s data is safe, and offer a next step. A retry button that does nothing visible is worse than none.
Announce state changes
A visual spinner is invisible to screen reader users. Mark a region that is updating with <code>aria-busy="true"</code> and set it back to false when the content is ready. For results that appear without a page load, use a polite live region such as <code>role="status"</code> so the update is announced without stealing focus.
Keep announcements short: “Loading results” and “12 results loaded” are enough.
Sources
- Nielsen Norman Group. Response Times: The 3 Important Limits. https://www.nngroup.com/articles/response-times-3-important-limits/
- W3C. WAI-ARIA 1.2, aria-busy and the status role. https://www.w3.org/TR/wai-aria-1.2/
This guide was drafted with AI assistance from public standards and references. For the exact wording of a standard, use the sources listed above.