Back to compare picker

Progress bar vs Loading spinner vs Loading skeleton vs Step navigation / step indicator

Use a progress bar when system progress is measurable; use a spinner for a short unknown wait, a skeleton for predictable pending content layout, and step navigation for user-driven task milestones.

Learn the decision

Match the interaction to the person's task

Use a progress bar when system progress is measurable; use a spinner for a short unknown wait, a skeleton for predictable pending content layout, and step navigation for user-driven task milestones.

Progress bar

Use it when: A system operation has a measurable total or bounded progress value.

Make this state clear: Idle state before the operation starts.

Observe the result: A user uploads evidence.zip, sees progress move from 12% to 64%, cancels before commit, retries after a network error, and gets a completed receipt only after server processing succeeds.

Study the full pattern →

Loading spinner

Use it when: The operation has defined resolution, timeout, cancellation, or failure paths.

Make this state clear: Inline processing state for a button or small local action.

Observe the result: After submit, users see payment PAY-2048 processing, can tell the button is temporarily unavailable, and then get either success or retry guidance.

Study the full pattern →

Loading skeleton

Use it when: The content shape is predictable.

Make this state clear: Initial skeleton placeholder state with region marked busy.

Observe the result: Users see that reports are pending, then can switch the demo to loaded, empty, or error outcomes on a bounded path.

Study the full pattern →

Step navigation / step indicator

Use it when: A linear form, application, checkout, or setup flow has three or more meaningful steps.

Make this state clear: Default state with completed, current, and upcoming steps.

Observe the result: After a user enters valid contact details and continues, Contact details becomes complete and Documents becomes current.

Study the full pattern →

Practice the judgment: Imagine this situation: An upload bar reaches 100% while server scanning is still running, so users leave before the attachment is accepted. Write the person's goal, choose one of these patterns, and show the state that helps the person continue. Use the decision rules and source trail below to explain your choice.

Review the underlying principle →

Decision dimensions

Dimension Progress barLoading spinnerLoading skeletonStep navigation / step indicator
UI or UX UI + UX - Measurable system-operation progress indicatorUI + UX - Bounded indeterminate wait indicator for a named action or regionUI + UX - Bounded content loading placeholderUI + UX - Linear multistep task progress indicator
UI guidance Show a labeled bar with a track, filled value, and nearby helper text that reports the measurable unit such as percent, bytes, rows, files, records, or stages.Render a compact spinner only beside, inside, or over the affected action, component, or page region, and pair it with concise text that names what is loading or processing.Keep skeleton dimensions stable, mark the affected region busy, and use subtle or reduced-motion-respecting animation only while loading is unresolved.Show a compact ordered list of named steps near the task heading, with visually distinct completed, current, upcoming, optional, and error states.
UX guidance Use a progress bar when the system can honestly report movement toward a known finish and users need to decide whether to wait, cancel, retry, continue elsewhere, or return later.Prevent duplicate or conflicting actions while the operation is in flight, but keep context, status, safe cancellation, and timeout recovery available when the wait exceeds the expected threshold.Reduce uncertainty and layout shift while predictable content loads, then resolve clearly to real content, empty state, or error state.Use step navigation to reduce uncertainty in long linear tasks by showing where users are, what is done, and what remains.
Good UI A document upload card says Uploading evidence.zip, shows 64%, 32 of 50 MB, a Cancel action, and keeps the rest of the form usable.A Pay invoice button becomes Processing payment with a small spinner, disables only duplicate payment actions, and leaves the invoice reference visible.The interface shows a clear action and state.A five-step application shows Eligibility complete, Contact details current, Documents upcoming, Review upcoming, and Submit upcoming, with the current step emphasized and a matching page heading.
Bad UI A progress bar reads 100% complete while virus scanning and server acceptance are still pending.A search results panel shows skeleton rows, a spinner, and a progress bar for the same request.Skeleton rows look like clickable report cards and receive focus before content exists.All future steps look clickable and complete even though required earlier fields are blank.
Good UX A user uploads evidence.zip, sees progress move from 12% to 64%, cancels before commit, retries after a network error, and gets a completed receipt only after server processing succeeds.After submit, users see payment PAY-2048 processing, can tell the button is temporarily unavailable, and then get either success or retry guidance.Users see that reports are pending, then can switch the demo to loaded, empty, or error outcomes on a bounded path.After a user enters valid contact details and continues, Contact details becomes complete and Documents becomes current.
Bad UX Users leave after 100% transfer even though server processing later rejects the file.The spinner blocks the whole workspace for a small table refresh and prevents users from continuing other work.Large layout shift after content arrives.The indicator says Step 4 of 5 while the page content and route still show Step 2.
Best fit A system operation has a measurable total or bounded progress value.The operation has defined resolution, timeout, cancellation, or failure paths.The content shape is predictable.A linear form, application, checkout, or setup flow has three or more meaningful steps.
Avoid when The wait is short and only needs scoped activity feedback.The content layout is predictable and a skeleton would better preserve structure.A specific progress indicator or blocking message is required.The journey has only one or two screens.
Required state Idle state before the operation starts.Inline processing state for a button or small local action.Initial skeleton placeholder state with region marked busy.Default state with completed, current, and upcoming steps.
Accessibility burden Provide an accessible name that identifies the operation and affected object.Give the spinner or affected region an accessible name that identifies the operation.Mark the loading region busy or provide concise status text.Use aria-current on the current labeled step and include hidden or visible status text for completed, current, upcoming, optional, and error states.
Common misuse Fabricating progress values just to make users feel movement.Showing an unlabeled spinner on a blank page.Showing skeletons forever.Using a step indicator as breadcrumbs, tabs, side navigation, or pagination.

Progress bar

UI or UX
UI + UX - Measurable system-operation progress indicator
UI guidance
Show a labeled bar with a track, filled value, and nearby helper text that reports the measurable unit such as percent, bytes, rows, files, records, or stages.
UX guidance
Use a progress bar when the system can honestly report movement toward a known finish and users need to decide whether to wait, cancel, retry, continue elsewhere, or return later.
Good UI
A document upload card says Uploading evidence.zip, shows 64%, 32 of 50 MB, a Cancel action, and keeps the rest of the form usable.
Bad UI
A progress bar reads 100% complete while virus scanning and server acceptance are still pending.
Good UX
A user uploads evidence.zip, sees progress move from 12% to 64%, cancels before commit, retries after a network error, and gets a completed receipt only after server processing succeeds.
Bad UX
Users leave after 100% transfer even though server processing later rejects the file.
Best fit
A system operation has a measurable total or bounded progress value.
Avoid when
The wait is short and only needs scoped activity feedback.
Required state
Idle state before the operation starts.
Accessibility burden
Provide an accessible name that identifies the operation and affected object.
Common misuse
Fabricating progress values just to make users feel movement.

Loading spinner

UI or UX
UI + UX - Bounded indeterminate wait indicator for a named action or region
UI guidance
Render a compact spinner only beside, inside, or over the affected action, component, or page region, and pair it with concise text that names what is loading or processing.
UX guidance
Prevent duplicate or conflicting actions while the operation is in flight, but keep context, status, safe cancellation, and timeout recovery available when the wait exceeds the expected threshold.
Good UI
A Pay invoice button becomes Processing payment with a small spinner, disables only duplicate payment actions, and leaves the invoice reference visible.
Bad UI
A search results panel shows skeleton rows, a spinner, and a progress bar for the same request.
Good UX
After submit, users see payment PAY-2048 processing, can tell the button is temporarily unavailable, and then get either success or retry guidance.
Bad UX
The spinner blocks the whole workspace for a small table refresh and prevents users from continuing other work.
Best fit
The operation has defined resolution, timeout, cancellation, or failure paths.
Avoid when
The content layout is predictable and a skeleton would better preserve structure.
Required state
Inline processing state for a button or small local action.
Accessibility burden
Give the spinner or affected region an accessible name that identifies the operation.
Common misuse
Showing an unlabeled spinner on a blank page.

Loading skeleton

UI or UX
UI + UX - Bounded content loading placeholder
UI guidance
Keep skeleton dimensions stable, mark the affected region busy, and use subtle or reduced-motion-respecting animation only while loading is unresolved.
UX guidance
Reduce uncertainty and layout shift while predictable content loads, then resolve clearly to real content, empty state, or error state.
Good UI
The interface shows a clear action and state.
Bad UI
Skeleton rows look like clickable report cards and receive focus before content exists.
Good UX
Users see that reports are pending, then can switch the demo to loaded, empty, or error outcomes on a bounded path.
Bad UX
Large layout shift after content arrives.
Best fit
The content shape is predictable.
Avoid when
A specific progress indicator or blocking message is required.
Required state
Initial skeleton placeholder state with region marked busy.
Accessibility burden
Mark the loading region busy or provide concise status text.
Common misuse
Showing skeletons forever.

Step navigation / step indicator

UI or UX
UI + UX - Linear multistep task progress indicator
UI guidance
Show a compact ordered list of named steps near the task heading, with visually distinct completed, current, upcoming, optional, and error states.
UX guidance
Use step navigation to reduce uncertainty in long linear tasks by showing where users are, what is done, and what remains.
Good UI
A five-step application shows Eligibility complete, Contact details current, Documents upcoming, Review upcoming, and Submit upcoming, with the current step emphasized and a matching page heading.
Bad UI
All future steps look clickable and complete even though required earlier fields are blank.
Good UX
After a user enters valid contact details and continues, Contact details becomes complete and Documents becomes current.
Bad UX
The indicator says Step 4 of 5 while the page content and route still show Step 2.
Best fit
A linear form, application, checkout, or setup flow has three or more meaningful steps.
Avoid when
The journey has only one or two screens.
Required state
Default state with completed, current, and upcoming steps.
Accessibility burden
Use aria-current on the current labeled step and include hidden or visible status text for completed, current, upcoming, optional, and error states.
Common misuse
Using a step indicator as breadcrumbs, tabs, side navigation, or pagination.
Decision rules
  • Choose progress bar when the system can expose percent complete, bytes transferred, item count, row count, batch count, or a bounded operation stage that moves toward a known finish.
  • Choose loading spinner when the operation is active but progress cannot yet be calculated and the expected wait is short enough for a compact indeterminate indicator.
  • Choose loading skeleton when the pending result has predictable layout and the user benefits from reserved card, row, or text structure before content arrives.
  • Choose step navigation when progress comes from a person completing named journey steps, not from system work such as upload, download, validation, processing, or import.
  • Do not show a percent bar if the value is fabricated, jumps backward, resets during one operation, or reaches 100% before the operation can honestly finish.
  • Switch from spinner or indeterminate bar to progress bar when the backend exposes enough information to report a meaningful value.
  • Switch from progress bar to success, error, retry, cancel, or background job status when the operation completes, fails, stalls, or is no longer worth blocking the current surface.
  • Use a progress bar inside the smallest affected scope: file row, import card, report job panel, dialog, or page region; do not block unrelated work unless the whole surface depends on the operation.
Inspect live examples
Failure modes
  • An upload bar reaches 100% while server scanning is still running, so users leave before the attachment is accepted.
  • A progress bar counts upward with no file size, row count, or stage data and then snaps backward after a retry.
  • A batch import has a measurable valid-row count but uses only a spinner, hiding whether work is moving.
  • A progress bar is used as a checkout stepper, confusing system processing with user task progress.
  • The label is far from the bar, so users cannot tell whether it belongs to the file upload, report export, or page load.
  • A failed operation leaves the bar active instead of showing a persistent error and recovery path.

Saved items