skip to content

Loading Indicators

Spinners, skeletons and progress bars signal waiting, each suited to a different wait length and certainty. Interviewers probe delay thresholds, layout shift, and announcing the busy state.

part ofDesign systems & UX foundationsoverview, primer and where to startread it →
on this pageshow

questions

5

In a design system's loading guidance, when should a screen use a spinner, a skeleton screen, or a progress bar?

level: juniorimportance: must knowfreq 60%

answer

  1. how long, and how much is known
  2. shape of the arriving content
  3. measurable work versus unknown work
  4. placeholder that mirrors the layout
  5. long jobs need a percentage or count

basics

~20 s

Choose by wait length and what is known: a skeleton when the arriving content's layout is known, a spinner for a short wait of unknown shape, and a progress bar when measurable work takes longer.

solid answer

~50 s

Each indicator answers a different question for the user. A **skeleton screen** says 'content shaped like this is coming' — it fits loading a known layout, such as a feed of activity cards, and makes the wait feel shorter because the page is already partly there. A **spinner** only says 'something is happening'; it fits short waits of a second or a few where nothing about the result is known, like saving an edited workout. A **progress bar** says 'this much is done' and fits long, measurable work — exporting a year of workouts or syncing forty sessions from a watch. Common practice is to show nothing for near-instant responses, a spinner or skeleton for waits of a few seconds, and a progress bar with a count or estimate once a wait runs past roughly ten seconds.

go deeper

for a junior

Recall the three indicators and the one question each answers: something is happening, content shaped like this is coming, or this much is done.

for a middle

Explain the choice in terms of wait length and knowledge: known layout favours a skeleton, measurable work a progress bar, and short unknown waits a spinner.

for a senior

Show you have seen these fail: mismatched skeletons that jump, timer-driven bars that stall, blocking spinners over partly usable screens, and how the system's guidance prevents them.

for a principal

Frame loading guidance as a system decision: one set of rules and timings shared across teams, versus each product inventing its own indicators and eroding trust in all of them.

## Three indicators, three different promises A **loading indicator** is any visual signal that the product has received a request and is working on it. Design systems usually ship three families of them, and the fastest way to choose between them is to ask what each one *promises* the user. | Indicator | What it tells the user | Best fit | Weak fit | |---|---|---|---| | **Spinner** (indeterminate, looping) | Something is happening; no idea how long | Short waits of unknown shape: saving, refreshing, a small fetch | Long waits, where it gives no sense of progress | | **Skeleton screen** (placeholder blocks shaped like the content) | Content shaped like this is on its way | First load of a screen whose layout is known: lists, cards, profiles | Background jobs with no visible result, or layouts that cannot be predicted | | **Progress bar** (determinate, filling) | This fraction of the work is done | Long, measurable work: uploads, exports, multi-item sync | Waits where no honest measure of progress exists | A **determinate** indicator shows how much is complete; an **indeterminate** one only shows activity. Spinners and skeletons are indeterminate; progress bars are usually determinate, though an indeterminate bar also exists for long work whose total is unknown. ## Choosing by wait length and certainty Two questions decide most cases: 1. **How long is the wait likely to be?** A widely cited set of response-time limits from usability research says roughly 0.1 s feels instant, about 1 s keeps the user's train of thought, and about 10 s is the limit of attention. These are guidance, not a standard, but they explain the usual bands. 2. **What do you know about the result?** If you know the *shape* of what is coming, a skeleton can draw it early. If you know the *amount* of work, a progress bar can measure it. If you know neither, a spinner is the honest choice. Put together, the common practice looks like this: - **Under a fraction of a second:** show no indicator at all; a flash of one reads as a glitch. - **Roughly one to ten seconds, known layout:** a skeleton that mirrors the content. - **Roughly one to ten seconds, unknown layout or a small action:** a spinner, placed where the result will appear. - **Past about ten seconds:** a progress bar with a count, a percentage or a stage label, and ideally a way to leave the screen while the work continues. ## Worked example: a fitness-tracker companion app - Opening the **activity feed** takes about two seconds and always renders the same card layout, so a skeleton of three or four cards fits — the user sees where the step counts and route maps will land. - **Pulling to refresh** today's heart-rate chart takes under a second and changes values rather than layout, so a small spinner at the top of the chart is enough. - **Syncing a week of sessions from the watch** processes a known number of workouts, so a progress bar reading '12 of 40 workouts' is both honest and reassuring. - **Exporting a full year of history** may take a minute; a progress bar plus a note that the export continues in the background lets the user do something else. ## Where each one goes wrong - A **full-screen spinner** that blocks the whole app for a two-second partial load hides content the user could already read. - A **generic skeleton** that does not match the real layout causes a visible jump when content arrives, which defeats its purpose. - A **progress bar driven by a timer** instead of real work stalls near the end and teaches users to distrust every bar in the product. - A **spinner on a long job** leaves users unable to tell a slow job from a stuck one, so they cancel or retry. ## What the system's spec usually writes down A loading guideline in a design system normally records, per indicator: when to use it, where it sits (in place of the content, not as a floating overlay, unless the whole screen is genuinely unavailable), the size variants, the label text pattern ('Syncing workouts'), the accessible name and announcement contract, and the timing rules — a short delay before showing and a minimum time once shown. Keeping those rules in one place is what stops each product team from inventing its own spinner.

  • Why does a skeleton screen often feel faster than a spinner for the same wait?
    A skeleton shows the structure of the page immediately, so the user starts orienting — where the title, stats and map will be — before data arrives. Attention moves to what is coming rather than to the waiting itself. A spinner gives nothing to look at except the wait. The actual duration is the same; the perceived duration usually is not, provided the skeleton matches the real layout.
  • Does WCAG treat a looping loading animation as moving content that needs a pause control?
    WCAG 2.2 SC 2.2.2 Pause, Stop, Hide (Level A) applies to moving content that starts automatically, lasts more than five seconds and sits in parallel with other content. Its Note 4 lets a preload animation count as essential when no interaction can happen during that phase and hiding progress would make users think the content was frozen. A long animation beside usable content falls outside that note, so it needs to stop, be hideable, or be justified as essential.
  • When is no loading indicator the right design?
    When the response is almost always fast enough to feel instant — well under a second — an indicator would only flash and draw attention to a wait nobody noticed. Also when the work can be done optimistically: the fitness app records a logged glass of water immediately and syncs in the background, reverting only if the save fails.

A restaurant host: 'your table is being set' is a skeleton, 'one moment please' is a spinner, and 'you are third in line' is a progress bar. Each is honest only when the host actually knows that much.

saying these in an interview costs you the question

  • A spinner is a safe default for every kind of wait
  • Any grey placeholder counts as a skeleton, whatever its shape
  • A skeleton screen tells users how much work is left
  • Long jobs should block the whole screen with a spinner
  • Showing an indicator for a 100 ms response is always better
open as a page

In a loading-indicator spec, why add a short delay before a spinner appears and a minimum time it stays visible once shown?

level: middleimportance: should knowfreq 46%

basics

~20 s

The delay keeps fast responses from flashing a spinner that reads as a glitch; the minimum display time stops a spinner that did appear from vanishing a split second later. Both remove flicker; neither slows fast responses.

open as a page

For a progress indicator in a design system, what decides determinate versus indeterminate, and what goes wrong when a team fakes determinate progress?

level: middleimportance: should knowfreq 42%

basics

~20 s

An indicator is determinate only when the product can measure completed work against a known total; otherwise it is indeterminate. Faked percentages stall, jump or run backwards, and teach users to distrust every progress bar.

open as a page

A screen-reader user taps Sync in a fitness app and hears nothing during a 20-second sync or when it ends — what should the loading indicator's accessibility contract specify?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Name the indicator, announce the wait and occasional progress without moving focus, announce completion or failure explicitly, and mark the updating region busy. WCAG 2.2 SC 4.1.3 Status Messages treats waiting and progress as status messages.

open as a page

In a fitness-tracker app, the workout-history screen's content jumps when real data replaces its skeleton, and users tap the wrong workout — why, and how do you fix it?

level: seniorimportance: should knowfreq 40%

basics

~20 s

The placeholder and the real content occupy different space, so arriving data pushes rows under the user's finger. Fix it by building skeletons from the real layout, reserving space for late media, and never inserting content above what the user is reading.

open as a page