Loading State
The visual feedback shown while content is being fetched or processed.
Plain English
A loading state is the UI's way of saying "I heard you — please wait." Without it, users have no idea if their click registered, if the network is slow, or if something broke. The key principles: show loading feedback within 100ms of any action, communicate progress where possible, and pick the right type of indicator for the context. Skeleton screens feel more responsive than spinners because they maintain layout and give a preview of what is coming.
Technical
Three main loading patterns: (1) Spinner — circular animated icon, best for small, bounded areas. (2) Skeleton screen — grey placeholder shapes matching the expected layout, best for content-heavy pages. (3) Progress bar — linear indicator, best for operations with measurable progress. Implement spinners with CSS animation: spin or SVG animation. Skeleton screens use shimmer (animated gradient) to signal activity. Always handle loading states in async React components with useState(true) initial loading, or via Suspense.
Live Demo
Loading State Patterns
1. Spinner
2. Skeleton
3. Progress Bar
0%
4. Loading Button
Show loading state within 100ms. Use skeletons for content, spinners for actions.
Usage
✓ Good usage
Replace the button label with a spinner and lock the button width on form submit — users see immediate feedback without the layout shifting.
✗ Bad usage
No loading state on form submission — users double-click, submit multiple times, and wonder if the page is broken.
Recommended values
- Show loading within 100ms of user action
- Spinner: 20–24px, accent colour, continuous rotation
- Skeleton: grey placeholder with shimmer animation, matches content layout
- Button loading: spinner + lock width to prevent layout shift
- Page loading: skeleton preferred over spinner for content pages
Common mistakes
- Not locking button width during loading — the button shrinks to spinner size, causing layout shift.
- Using spinner for page-level loading (jarring) — use skeleton screens instead.
- Infinite loading with no timeout or error recovery.
AI Prompt Example
Copy this into Claude, Cursor, Bolt, or v0.
On form submit: disable button, replace label with inline spinner, lock width to prevent layout shift. For data fetching: show a skeleton screen matching the content layout for the first load. Spinner: 20px, accent colour, animation: spin 700ms linear infinite.