UI + UX Feedback, Status, And System State established

Loading skeleton

Reserve the approximate final content structure with neutral non-interactive placeholders, mark the region busy, then replace the skeleton with loaded content, empty state, or error state on a bounded path.

Decision first

Choose this pattern when the problem matches

Use when

  • The content shape is predictable.
  • Loading is short or bounded enough that the placeholder meaning remains clear.
  • Users benefit from knowing where asynchronous content will appear.

Avoid when

  • The system cannot predict the content layout.
  • A specific progress indicator or blocking message is required.
  • The operation is long-running and users need job progress, queue position, or cancellation.
  • The result is already known to be empty, failed, or filtered out.
  • The placeholder would look like a disabled control users try to interact with.

Problem it prevents

Users need to know that predictable content is still loading while the layout stays stable and placeholders are not mistaken for real, interactive content.

Pattern anatomy

What a strong implementation has to make clear

User need

Content loads asynchronously and has a predictable final shape such as cards, rows, profile blocks, charts, or media tiles.

Pattern promise

Reserve the approximate final content structure with neutral non-interactive placeholders, mark the region busy, then replace the skeleton with loaded content, empty state, or error state on a bounded path.

Required state

Initial skeleton placeholder state with region marked busy.

Recovery path

Infinite placeholder with no error state.

Access contract

Mark the loading region busy or provide concise status text.

Quality bar

The difference between expert and weak execution

Strong implementation

Specific, visible, recoverable

  • Three report-card placeholders match the final card heights and are replaced by real cards without shifting the panel.
  • The loading region is marked busy and placeholders are plain shapes with no readable fake labels or focusable buttons.
  • Users see that reports are pending, then can switch the demo to loaded, empty, or error outcomes on a bounded path.
  • If loading fails, the UI moves to a persistent error state instead of continuing shimmer forever.
Weak implementation

Vague, hidden, hard to recover from

  • Skeleton rows look like clickable report cards and receive focus before content exists.
  • A spinner and skeleton compete for the same region while the final content appears in a different layout.
  • Skeleton never resolves.
  • Keyboard focus enters placeholder-only controls or users tap fake rows that are not real content.
UI guidance
  • Render neutral skeleton blocks that reserve the final content structure without fake readable text, fake controls, or focusable placeholder elements.
  • 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.
  • Use skeletons for short bounded waits and switch to explicit progress, cancellation, or error recovery when the wait becomes long or fails.
Implementation contract

What the implementation must handle

States

  • Initial skeleton placeholder state with region marked busy.
  • Loaded state where real content replaces placeholders without layout jump.
  • Resolved empty state after successful loading returns no content.
  • Failure or timeout state after loading cannot complete.

Interaction

  • Skeleton placeholders are not focusable, clickable, selectable, or announced as real content.
  • The placeholder geometry approximates the loaded content closely enough to reduce layout shift.
  • The loading region communicates pending status without announcing every placeholder row.
  • Loading cannot continue indefinitely without switching to error, timeout, or support messaging.

Accessibility

  • Mark the loading region busy or provide concise status text.
  • Avoid announcing every skeleton row as content.
  • Do not place keyboard focus inside placeholder-only controls.
  • Respect reduced-motion preferences for shimmer or pulse animation.

Review

  • Does this placeholder communicate pending structure without pretending content exists?
  • What exact state replaces the skeleton if loading succeeds, returns empty, fails, or times out?
  • Can keyboard and screen reader users avoid interacting with placeholder-only content?
Interactive lab

Inspect the states before you copy the pattern

Preview loading structure

Inspect whether loading preserves layout without pretending content is available.

Loading skeleton
Interactive demo is ready

Launch the live UI/UX lab when you want to inspect states, keyboard behavior, and common failure modes.

State To Inspect

Initial skeleton placeholder state with region marked busy.

Keyboard / Access

Do not place keyboard focus inside placeholder-only controls.

Avoid Generating

Showing skeletons forever.

Evidence trail

Source-backed claims behind this guidance

Carbon Design System Loading

IBM Carbon Design System - checked

Carbon distinguishes loading indicators and skeleton states, recommending skeleton states for progressively displayed content.

SAP Fiori Skeleton Loading

SAP Fiori - checked

SAP Fiori documents skeleton loading as a screen loading progress indicator and warns against mixed progress indicators.

Nord Design System Skeleton

Nord Design System - checked

Nord documents dynamic-content skeletons, aria-busy regions, and removing busy state after load.

Cedar Design System Skeleton

REI Co-op Cedar Design System - checked

Cedar documents skeletons for regions, not specific interactive elements, and reduced-motion behavior.

Full agent/debug reference

Problem Context

  • Content loads asynchronously and has a predictable final shape such as cards, rows, profile blocks, charts, or media tiles.
  • A blank screen or centered spinner would not show where content will appear or would allow avoidable layout shift.
  • The system can distinguish loading from loaded, empty, failed, and timed-out states.

Selection Rules

  • Choose skeletons when the final content layout is known enough to reserve stable space.
  • Use skeletons for dynamic content regions rather than standalone buttons, inputs, or controls.
  • Keep skeletons neutral and abstract so they do not look like real text, fake data, or tappable controls.
  • Mark the loading region busy or provide a concise status so assistive technology does not treat placeholders as content.
  • Transition to loaded content, empty state, error state, or cancelled state on a bounded timeline.
  • Respect reduced-motion preferences when using shimmer or pulse animation.
  • Use progress bars, inline loading, or explicit job status instead when progress is measurable or the task blocks action.

Required States

  • Initial skeleton placeholder state with region marked busy.
  • Loaded state where real content replaces placeholders without layout jump.
  • Resolved empty state after successful loading returns no content.
  • Failure or timeout state after loading cannot complete.
  • Reduced-motion state for animated skeletons.
  • Refresh or partial-loading state where existing content remains trustworthy while only new areas are busy.

Interaction Contract

  • Skeleton placeholders are not focusable, clickable, selectable, or announced as real content.
  • The placeholder geometry approximates the loaded content closely enough to reduce layout shift.
  • The loading region communicates pending status without announcing every placeholder row.
  • Loading cannot continue indefinitely without switching to error, timeout, or support messaging.
  • Existing user focus remains stable while new content loads unless focus movement is required after completion.
  • When loaded content arrives, busy state is removed and real controls become available.

Implementation Checklist

  • Reserve stable dimensions for every skeleton region.
  • Match skeleton row, card, media, and text proportions to the final content density.
  • Avoid fake readable text and fake interactive controls.
  • Use aria-busy or equivalent status for the affected region.
  • Remove busy state when content, empty, or error state resolves.
  • Add timeout or failure handling so skeletons do not run forever.
  • Honor prefers-reduced-motion when animating shimmer or pulse.
  • Do not combine skeletons with competing spinners unless each indicator applies to a clearly different region.

Common Generated-UI Mistakes

  • Showing skeletons forever.
  • Using skeletons for unknown layout shapes.
  • Making placeholders look like tappable content.
  • Showing skeleton after a no-results or empty response is already known.
  • Leaving shimmer animation on for reduced-motion users.
  • Loading into a layout that has little relationship to the placeholder.

Critique Questions

  • Does this placeholder communicate pending structure without pretending content exists?
  • What exact state replaces the skeleton if loading succeeds, returns empty, fails, or times out?
  • Can keyboard and screen reader users avoid interacting with placeholder-only content?
Accessibility
  • Mark the loading region busy or provide concise status text.
  • Avoid announcing every skeleton row as content.
  • Do not place keyboard focus inside placeholder-only controls.
  • Respect reduced-motion preferences for shimmer or pulse animation.
  • Remove busy state when the region resolves to loaded, empty, or error.
Keyboard Behavior
  • Do not place keyboard focus inside placeholder-only controls.
  • Keep existing focus stable while content loads.
  • Make real controls focusable only after data resolves.
  • If loading fails, focus should remain near or move predictably to the persistent error state.
Variants
  • Card skeleton
  • Table row skeleton
  • Text skeleton
  • Media skeleton
  • Chart skeleton
  • Partial-region skeleton
  • Reduced-motion static skeleton

Verification

Last verified: