Loading State Design

Loading states are part of the experience, not a gap in it. Good ones set expectations, keep the layout stable and make the wait feel shorter.

By Mohamed Farhan · Updated Oct 19, 2026

Inside the example

The live example above is plain HTML with Tailwind utility classes, so you can paste it into any Tailwind project. It uses the default type size and spacing p-5 (20px), gap-3 (12px), space-y-2 (8px), mt-5 (20px), constrained by max-w-md and w-10 and w-1/3 and w-1/2 and w-5/6 and w-2/3. Everything sits on a 4px grid, which keeps rhythm consistent when you adapt it.

Colors use Tailwind's neutral stone scale so the pattern stays brand-agnostic. Swap stone-900 for your primary color on the main action, keep body text dark and check contrast after any change.

Anatomy

1.Skeleton
Grey placeholders shaped like the coming content.
2.Spinner
For short, unknown waits on small areas.
3.Progress bar
For long waits with known progress.
4.Status text
For waits longer than a few seconds.

Common variations

  • Skeleton screens, placeholder shapes that match the content layout.
  • Spinners, for short, small-scale waits such as a button submit.
  • Progress bars, for long tasks with known progress.
  • Optimistic UI, where the interface updates immediately and syncs in the background.

States to design

  • Initial load: skeleton or placeholder content.
  • Refreshing: previous content stays visible with a subtle indicator.
  • Long running: progress, time estimate and the option to continue working.
  • Failed: an error with retry, preserving what the user already did.

A walkthrough

A finance manager opens a dashboard on a slow hotel connection. Instead of a blank page or a single spinner, she sees the layout immediately: skeleton cards for each metric and grey rows where the table will be. The numbers fill in one card at a time, and nothing jumps around as they appear.

She starts generating a quarterly report. A progress bar and the message 'This usually takes about 20 seconds' appear, and she keeps working on other screens. When the report is ready, a notification lets her know. When one chart fails to load because of the connection, only that chart shows an error with a Retry button, while the rest of the dashboard keeps working.

The team that built the dashboard also tuned the small details: spinners only appear if a request takes longer than about 300ms, so quick actions never flicker, and the shimmer on skeletons is turned off for people who have reduced motion enabled in their operating system. Loading regions are marked as busy, so screen reader users know content is still on its way.

How different products use it

Social and content feeds use skeleton cards that match post layouts, then fill in content progressively.

Dashboards load each widget independently so one slow chart does not block the rest.

AI and generation tools show streaming output or step-by-step progress for tasks that take tens of seconds.

Visual design guidelines

Skeletons should use a neutral tone close to the surface color, with rounded shapes that match the real content dimensions. If you animate them, use a slow, subtle shimmer and disable it with prefers-reduced-motion. Spinners should be small (16 to 24px) and placed where the result will appear. Progress bars need a full, clearly visible track.

Best practices

Do

  • Use skeletons that match the real layout to avoid content jumping.
  • Show progress for operations longer than about 10 seconds.
  • Keep previous content visible while refreshing.
  • Respect reduced-motion preferences for shimmer effects.

Don't

  • Do not block the whole page for a small update.
  • Do not show a spinner for operations under about 300ms; it flickers.
  • Do not loop vague messages like 'Almost there' forever.

On mobile

On mobile, network conditions vary widely, so show content progressively and avoid blocking the whole screen. Pull-to-refresh is common in feeds, and offline states should tell users what still works.

Common mistakes

  • Full-page spinners for small updates.
  • Flashing indicators on very fast requests.
  • Layout shift when content replaces placeholders of a different size.
  • Infinite spinners with no timeout or error state.

Edge cases to plan for

  • Partial failures, where some content loads and some does not, need per-section errors.
  • Very slow connections should still show useful content first.
  • Background refreshes should not reset scroll position or user input.
  • Long tasks should survive page navigation or notify when complete.

Accessibility checklist

  • Mark loading regions with aria-busy="true".
  • Announce completion for long operations.
  • Turn off shimmer animation when prefers-reduced-motion is set.

Implementation notes

Set aria-busy="true" on regions that are loading and remove it when done. Delay showing spinners by about 300ms. Size skeletons to match real content to avoid layout shift, and disable shimmer animation when prefers-reduced-motion is set.

In your design system

In a design system, loading states include skeleton primitives (text line, avatar, card, table row), a spinner, a progress bar and an inline status. Give skeletons the same dimensions as the components they stand in for, and document when to use each indicator so teams do not default to full-page spinners.

How to measure whether it works

Measure real loading times with performance monitoring and track Cumulative Layout Shift. Users tolerate longer waits when progress is visible, so compare satisfaction and drop-off before and after adding better loading states.

Pre-launch checklist

Microcopy you can use

Long taskGenerating your report. This usually takes about 20 seconds.
BackgroundSaving...

A step-by-step design process

  • Measure real load times to know which waits are short and which are long.
  • Choose the right indicator for each: skeleton, spinner or progress.
  • Design skeletons that match real layouts to prevent shifting.
  • Design long-running states with progress and estimates.
  • Design failure and retry for every loading state.
  • Respect reduced motion for animated loaders.

Usability test tasks

Before shipping, run a short usability test with five or so people from your audience. Give them tasks rather than instructions and watch where they hesitate:

  • Tell whether the page is still loading.
  • Keep working while a report generates.
  • Retry after a failed load.
  • Notice when a background save completes.

Key terms

  • Skeleton screen: Placeholder shapes shown while content loads.
  • Optimistic UI: Updating the interface before the server confirms.
  • Layout shift: Content moving unexpectedly as the page loads.
  • aria-busy: An attribute that marks a region as updating.

Writing the copy

For long tasks, explain what is happening and how long it usually takes: 'Generating your report. This usually takes about 20 seconds.' Avoid vague or jokey messages that repeat forever. For background saves, short status text like 'Saving...' and 'Saved' is enough.

Prompts to generate variations

If you use an AI UI generator such as Inspo AI, these prompts are a good starting point for exploring variations of this pattern:

  • Design loading states for a dashboard: skeleton cards, table rows and an inline saving indicator.
  • Create a long-running export screen with progress, time estimate and a notify-me option.
  • Design a streaming AI response state with a stop button and partial results.

Related patterns

Loading states connect to error messages when something fails, file upload progress, and toast notifications when background work finishes.

Generate this pattern for your product

Inspo AI designs the full pattern with every state, grounded in how real products solve it, and exports React + Tailwind.

Generate this pattern

Sources and further reading

More UI patterns

Questions people ask

Skeleton screen or spinner?

Use skeletons when loading page content with a known layout, and spinners for small, short actions like a button submit.

How long before showing a loading indicator?

Wait about 300ms before showing one, so fast responses do not cause a flicker.

Do skeleton screens improve perceived speed?

They help by showing structure immediately and keeping the layout stable, which makes waits feel shorter.

What is optimistic UI?

Updating the interface immediately as if an action succeeded, then reconciling with the server. It makes apps feel instant but needs a clear rollback when something fails.

Do skeleton screens help SEO?

Not directly. For SEO, important content should be server-rendered rather than loaded behind placeholders.

Mohamed Farhan
Mohamed Farhan•Author & CEO•LinkedIn

↘ Building Inspo AI | AI-Powered Design Research & Builder Platform | Design Engineer.