Back to compare picker

Offline state vs Error state vs Loading spinner vs Progress bar

Choose offline state when the device or app cannot reach the network and users need to know which cached data, local edits, queued actions, and retry paths remain available.

Decision dimensions

Dimension Offline stateError stateLoading spinnerProgress bar
UI or UX UI + UX - Connectivity-mode and local-work continuity stateUI + UX - Recoverable failure surfaceUI + UX - Bounded indeterminate wait indicator for a named action or regionUI + UX - Measurable system-operation progress indicator
UI guidance Show offline status where it changes the current task, naming what remains available such as cached reports, local draft editing, queued saves, or read-only history.Render a persistent error region near the affected content with a specific failure heading, plain-language cause, preserved context, and recovery actions.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.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 offline state to preserve trust and task continuity when connection loss changes what users can read, edit, submit, sync, refresh, or share.Help users recover when expected loading, saving, validation, sync, permission, or computation fails without losing their work.Use a loading spinner for short indeterminate waits where the system is actively working but cannot yet expose progress; resolve it quickly to content, success, cancellation, progress, or error.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 field report says Offline: 3 edits saved on this device, cached customer history shown from 10:42, Submit disabled until connection returns, and Retry connection.Reports could not load appears in the report section with the saved filter, Retry, Use cached data, and Contact support actions.A Pay invoice button becomes Processing payment with a small spinner, disables only duplicate payment actions, and leaves the invoice reference visible.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 blank page says You are offline even though the app has cached drafts and help content.Tiny transient toast for a blocking failure.A blank page shows a large spinner with no text, no affected object, and no idea what is loading.A blue bar fills across the top of the page with no label, no percent, and no affected object.
Good UX A user loses connection while editing an inspection note, sees it saved on this device, attaches photos to a queue, and later watches the queue sync after reconnect.User input and filter context are preserved after failure, and retry returns to recovered content or a clear still-failed state.After submit, users see payment PAY-2048 processing, can tell the button is temporarily unavailable, and then get either success or retry guidance.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 The app keeps a spinner on Save during airplane mode and never explains that no network request can start.Clearing work after save failure.The spinner blocks the whole workspace for a small table refresh and prevents users from continuing other work.A fake progress bar inches to 99% for minutes with no elapsed time, cancel, retry, or background option.
Best fit Connection loss or server reachability changes the user's current task.A system or task failure blocks expected content or action.A short action, request, save, submit, refresh, sync, or fetch is actively processing and progress cannot be meaningfully measured.A system operation has a measurable total or bounded progress value.
Avoid when A single request failed while the rest of the app is reachable and an error state is clearer.Nothing exists yet and the state is expected.The content layout is predictable and a skeleton would better preserve structure.Progress cannot be measured or would be guessed.
Required state Online normal state with no offline warning.Normal expected state before failure.Idle state with no spinner and the action or region ready.Idle state before the operation starts.
Accessibility burden Announce significant connectivity changes with status messaging when they affect the current task.Use appropriate alert or status semantics for newly appearing critical errors.Give the spinner or affected region an accessible name that identifies the operation.Provide an accessible name that identifies the operation and affected object.
Common misuse Showing only a browser-style offline page when useful cached or local content exists.Using a transient toast for critical errors.Showing an unlabeled spinner on a blank page.Fabricating progress values just to make users feel movement.

Offline state

UI or UX
UI + UX - Connectivity-mode and local-work continuity state
UI guidance
Show offline status where it changes the current task, naming what remains available such as cached reports, local draft editing, queued saves, or read-only history.
UX guidance
Use offline state to preserve trust and task continuity when connection loss changes what users can read, edit, submit, sync, refresh, or share.
Good UI
A field report says Offline: 3 edits saved on this device, cached customer history shown from 10:42, Submit disabled until connection returns, and Retry connection.
Bad UI
A blank page says You are offline even though the app has cached drafts and help content.
Good UX
A user loses connection while editing an inspection note, sees it saved on this device, attaches photos to a queue, and later watches the queue sync after reconnect.
Bad UX
The app keeps a spinner on Save during airplane mode and never explains that no network request can start.
Best fit
Connection loss or server reachability changes the user's current task.
Avoid when
A single request failed while the rest of the app is reachable and an error state is clearer.
Required state
Online normal state with no offline warning.
Accessibility burden
Announce significant connectivity changes with status messaging when they affect the current task.
Common misuse
Showing only a browser-style offline page when useful cached or local content exists.

Error state

UI or UX
UI + UX - Recoverable failure surface
UI guidance
Render a persistent error region near the affected content with a specific failure heading, plain-language cause, preserved context, and recovery actions.
UX guidance
Help users recover when expected loading, saving, validation, sync, permission, or computation fails without losing their work.
Good UI
Reports could not load appears in the report section with the saved filter, Retry, Use cached data, and Contact support actions.
Bad UI
Tiny transient toast for a blocking failure.
Good UX
User input and filter context are preserved after failure, and retry returns to recovered content or a clear still-failed state.
Bad UX
Clearing work after save failure.
Best fit
A system or task failure blocks expected content or action.
Avoid when
Nothing exists yet and the state is expected.
Required state
Normal expected state before failure.
Accessibility burden
Use appropriate alert or status semantics for newly appearing critical errors.
Common misuse
Using a transient toast for critical errors.

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
Use a loading spinner for short indeterminate waits where the system is actively working but cannot yet expose progress; resolve it quickly to content, success, cancellation, progress, or error.
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 blank page shows a large spinner with no text, no affected object, and no idea what is loading.
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
A short action, request, save, submit, refresh, sync, or fetch is actively processing and progress cannot be meaningfully measured.
Avoid when
The content layout is predictable and a skeleton would better preserve structure.
Required state
Idle state with no spinner and the action or region ready.
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.

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 blue bar fills across the top of the page with no label, no percent, and no affected object.
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
A fake progress bar inches to 99% for minutes with no elapsed time, cancel, retry, or background option.
Best fit
A system operation has a measurable total or bounded progress value.
Avoid when
Progress cannot be measured or would be guessed.
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.
Decision rules
  • Choose offline state when the device or app cannot reach the network and users need to know which cached data, local edits, queued actions, and retry paths remain available.
  • Choose error state when a specific load, save, submit, permission, validation, sync, or computation attempt has failed and the affected object needs persistent recovery.
  • Choose loading spinner when a named action or region is actively working for a short indeterminate wait and has not yet resolved to offline, success, failure, or progress.
  • Choose progress bar when the system can report a meaningful numeric value for upload, download, import, export, validation, or processing work.
  • Do not replace an offline mode with a blank error page when cached content, local drafts, read-only history, or queued saves can still be useful.
  • Do not claim work is saved online while offline; label it as saved on this device, queued, waiting to sync, or sync failed.
  • Use offline state at the smallest honest scope: whole app, page, panel, record, action, or field, depending on what connectivity actually blocks.
  • When connection returns, transition from offline to syncing, synced, conflict, or failed state instead of silently hiding queued changes.
Inspect live examples
Failure modes
  • A disconnected form says Saved even though the answer exists only on the device and may conflict later.
  • The app shows a browser-style offline page even though the dashboard, drafts, and help articles were cached.
  • All controls are disabled because the network is gone, including safe read-only navigation and local editing.
  • A spinner runs forever during connection loss instead of switching to offline state with retry and cached data.
  • A progress bar pretends to upload while the request is queued locally with no network.
  • The app reconnects and clears the offline banner without syncing queued changes or surfacing conflicts.