Field Notes
All posts

In defense of the humble loading state

Spinners, skeletons and progress bars each say something different about the wait. Choose the one that tells the truth.

Every wait needs a face

Some operations take time no matter how well a system is built: uploading a file, generating a report, loading a page on a slow connection. What the interface shows during that time shapes how long the wait feels and whether people trust that something is happening.

Under a second: often nothing

For operations that usually complete in a few hundred milliseconds, showing a spinner immediately can make things feel slower, because the spinner flashes briefly and draws attention to a wait that would otherwise go unnoticed. A common approach is to delay the indicator by 300 to 500 milliseconds and show it only if the operation is still running.

Spinners

A spinner says "something is happening, and I do not know how long it will take". It is honest for short, indeterminate waits. For longer waits it becomes anxious: after ten seconds of spinning, people start to wonder whether anything is happening at all.

Place the spinner where the result will appear, and pair it with a short label if the wait might be noticeable: "Loading posts" is more reassuring than a lone circle.

Skeleton screens

A skeleton shows the shape of the content that is coming, rendered as gray placeholders. It sets expectations about layout, avoids a jarring shift when content arrives, and tends to make waits feel shorter. Skeletons work best when the layout is predictable, such as a list of cards or an article.

Keep skeletons faithful to the real layout. A skeleton with three rows that resolves into twelve is nearly as jarring as no skeleton.

Progress bars

When progress can be measured, show it. A determinate progress bar tells people how far along the operation is and lets them decide whether to wait. Uploads, multi-step imports, and long exports all benefit. Make sure the bar never moves backward, and avoid bars that race to 90 percent and then sit there.

Optimistic updates

Sometimes the best loading state is none. When an action is very likely to succeed, such as liking a post or checking off a task, update the interface immediately and send the request in the background. If it fails, roll back and say so. The interface feels instant.

Errors are not loading states

A request that failed must not keep spinning forever. Set timeouts, and when one fires, replace the indicator with a clear message and a way to retry.

Test on slow connections

Loading states are invisible on a fast developer machine. Throttle your connection in developer tools and walk through the main flows. The waits your visitors experience every day will become obvious.