Loading

State

Loading

Loading is the state that tells the user the screen is busy fetching something, easing the anxiety of the wait with a spinner or skeleton.

Pattern

Definition

Loading is the state that tells the user the screen is busy fetching something right now. You might show a spinner that circles endlessly, or a skeleton that lays down gray placeholder shapes exactly where the real content will land, hinting that it is about to fill in. If you leave the screen blank while data travels from the server, people cannot tell whether it is thinking or broken, and that uncertainty makes them anxious. A loading indicator fills that empty stretch of time and quietly says, "I am working on it, hang tight for a moment." You will find it almost everywhere a result does not appear instantly: pulling up a list, opening a screen for the first time, or tapping a button to save.

Why does it matter?

When a screen sits frozen with no response, people feel the wait as far longer and more frustrating than it actually is. A few silent seconds can feel like forever, and users may hit refresh or close the window entirely. A loading state tames that anxiety. Just a visual sign that something is happening makes people wait far more patiently. Skeletons in particular preview the shape the final screen will take, so even when the real speed is identical, the perceived speed feels noticeably faster. Simply making the result predictable changes the quality of the wait. Without any indicator, no matter how fast the server is, the screen comes across as sluggish and untrustworthy. In the end a loading state is less about raw performance and more about how the person experiences the wait. The same three seconds feel short in front of a well-designed loader, and endless in front of silent, empty stillness.

Common mistakes

  • Showing a loading indicator even for very short waits. When a spinner flashes for something that finishes in a tenth of a second, the screen looks messy and unstable. All that remains is a jarring flicker.
  • Leaving the screen untouched with no indicator even when it takes more than a second. Users assume it is stuck, tap the same button again, or leave altogether.
  • Building a skeleton whose shape is nothing like the real content. When the placeholder and the actual layout differ in size or position, the moment the content arrives the layout jumps and looks even more chaotic.

Practical tips

  • Use a spinner when the wait is short and the result's position is hard to predict, and a skeleton when the incoming content has a clear place to go. Skeletons preview the final look and noticeably raise the perceived speed.
  • Always add a loading indicator for tasks that take more than a second, but skip it for very short waits. A flicker in that brief gap only makes the screen look unstable.
  • Match the skeleton's size and placement as closely as possible to the real content. When the space is reserved precisely, the layout does not jump as content fills in and the transition stays smooth.

Ask your AI

When the screen sits blank while loading

In the component I'll paste below, find every spot that just sits blank while it waits for data. For any request that might take more than 1 second, always add a loading indicator: use a skeleton for lists, cards, and profiles where the incoming content has a clear place to land, and a spinner for short actions where the result's position is hard to predict. For instant actions that finish within 0.1 second, show nothing at all. Give me the updated code plus a note on which one you chose for each spot and why.

When the layout jumps after loading finishes

Using the real markup of the [component — e.g. product card list] I'll paste below, build a skeleton whose size, position, and spacing match it exactly. Reserve the same width, height, and line count the real content will occupy so the layout doesn't jump (zero CLS) the moment data arrives. A skeleton that doesn't match the real screen only looks messier, so align the text lines, thumbnail, and button positions as closely to the real thing as possible. Return the skeleton component code and explain how you matched each part to the real content.

When a spinner flickers on fast responses

In the loading logic I'll paste below, fix the spinner that flashes in and out in an instant. Don't show it the moment the request starts—delay it so the spinner only appears if the request is still running after about 300ms, so anything that finishes within 0.1 second never shows one at all. Once it does appear, keep it visible for at least 500ms so it doesn't vanish the instant it shows up. Pull this delay-and-minimum logic into a reusable hook or function and give me the updated code.

Related concepts