Skip to content
Back to skills

Loading States And Perceived Performance

ASecurity

Manage user expectations during wait times with appropriate loading states — from simple spinners to complex skeleton screens and staggered animations. Perceived performance is often more important than actual load time. Use when designing data-heavy components, handling API calls, building hero sections, or improving the feel of a slow interface.

  • 15 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
designrustspringapidatabaseperformance

Works with

  • api

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add youlianvr/oper-share --skill loading-states-and-perceived-performance --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Loading States And Perceived Performance?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Loading States And Perceived Performance
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/youlianvr-loading-states-and-perceived-performance/badge)](https://www.skillsdirectory.com/skills/youlianvr-loading-states-and-perceived-performance)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: loading-states-and-perceived-performance
description: >-
  Manage user expectations during wait times with appropriate loading states — from simple spinners to complex skeleton screens and staggered animations. Perceived performance is often more important than actual load time. Use when designing data-heavy components, handling API calls, building hero sections, or improving the feel of a slow interface.
metadata:
  priority: 7
  pathPatterns:
  - components/**
  - src/components/**
  - '**/*.tsx'
  - '**/*.jsx'
  - '**/*.css'
  - '**/*.scss'
  - design-system/**
  promptSignals:
    phrases:
    - loading state
    - spinner
    - skeleton screen
    - skeleton loader
    - perceived performance
    - loading animation
    - shimmer effect
    - staggered loading
    - prefetch
    - prioritise loading
    - progressive loading
    - lazy load data
retrieval:
  aliases:
  - loading states
  - skeleton loaders
  - spinners
  - perceived performance
  - shimmy
  - glimmer
  - prefetching
  - priority loading
  - progressive data loading
  intents:
  - design a loading state
  - add a skeleton screen
  - improve perceived performance
  - choose between spinner and skeleton
  - handle slow data loading
  - adding delight to the wait
  - load the most important content first
  - prefetch the likely next step
  examples:
  - what loading state should this card use
  - add a skeleton loader for this list
  - make the page feel faster while loading
  - design a spinner for this button
  - load the key content first then stream the rest
  - prefetch the next page so it feels instant
---
# Loading States and Perceived Performance

Show what is loading and, when measurable, its progress.

---

## Choosing the Right Loading State

| Wait Duration | Best Pattern | Use for |
|---|---|---|
| **Short (< 1s)** | **Inline Spinner / Loader** | Button actions, small updates, quick data fetches |
| **Medium (1s – 3s)** | **Skeleton Screen** | Cards, lists, dashboards, profile pages |
| **Long (> 3s)** | **Determinate Progress Bar** | File uploads, complex exports, heavy processing |
| **Full Page** | **Staggered Entry / Animated Sections** | Initial app load, hero sections, immersive transitions |

---

## Simple Cases: Spinners and Loaders

Use spinners for small, contained actions where the layout doesn't change significantly.

- **Button Spinners:** Replace button text or sit alongside it. The button should enter a `disabled` state to prevent double-submissions.
- **Micro-Loaders:** A small 16–24px circle for inline updates (e.g., saving a single field).
- **Animation Tip:** Use eased rotation for the spinner, as in the example below.

```css
@keyframes spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.spinner {
  animation: spin 800ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
```

---

## Skeleton Screens (Glimmer/Shimmer)

Skeleton screens provide a visual placeholder that mimics the layout of the final content. This reduces "layout shift" (CLS) and signals to the user exactly where the content will appear.

### The Shimmer Effect
A subtle, moving gradient that travels across the skeleton elements.

```css
.skeleton {
  background: var(--color-grey-100);
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.5) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
```

### Rules for Skeletons
- **Match the shape:** If the final content is a round avatar, use a round skeleton. If it's a 2-line heading, use two bars of varying widths.
- **Stay Recessive:** Skeletons should use your most subtle grey (`--color-grey-100` or `grey-50`). They should not draw focus.
- **Fade into Reality:** When data arrives, fade the actual content in over the skeleton (150–200ms) rather than snapping.

---

## Fully Animated Sections

For major page transitions or initial loads, use a coordinated animation strategy.

### Staggered Entry (Cascading)
Instead of the whole page appearing at once, animate sections in a sequence. This guides the user's eye from the most important content (hero) down to secondary areas.

```css
.section {
  opacity: 0;
  transform: translateY(10px);
  animation: slide-up 400ms ease-out forwards;
}
/* Stagger by index */
.section:nth-child(1) { animation-delay: 100ms; }
.section:nth-child(2) { animation-delay: 200ms; }
.section:nth-child(3) { animation-delay: 300ms; }

@keyframes slide-up {
  to { opacity: 1; transform: translateY(0); }
}
```

### Hero Section "Bloom"
For hero sections, you might use a more complex animation:
1. **Background image** fades in slowly.
2. **Heading** slides in with a slight overshoot (spring).
3. **CTA button** appears last with a crisp fade-in or subtle color transition.

---

## Load in Priority Order — and Prefetch What's Next

Load in order of **value to the user** and render each tier as it becomes ready.

- **First, the highest-value content** — the key figure, the primary record, the above-the-fold answer. Render it the moment it's ready.
- **Then the next tier, then the next** — secondary panels, related lists, and below-the-fold sections stream in behind it (skeletons hold their space so nothing shifts — see the skeleton section above).
- **Fetch only what the current view needs.** Defer data for tabs, drawers, and off-screen sections until they're opened, rather than loading the whole page's worth of data at once.

**Prefetch the predictable next step** — next page, a hovered row's detail, the next wizard step — in the background so it's instant. Don't speculatively load everything; only where there's an obvious next move.

## Advanced: Optimistic UI

- **The Pattern:** Update the UI immediately assuming the server call will succeed. If it fails, roll back and show an error.
- **Use for:** Liking a post, toggling a switch, renaming a folder, deleting a message.

---

## Adding Delight to the Wait

Loading doesn't have to be a neutral experience. For waits longer than 2 seconds, consider adding brand personality and "delight" to keep the user engaged.

### Brand-Aligned Micro-copy
Replace generic "Loading..." text with wording that reflects the brand's voice.
- **Technical:** "Compiling data...", "Syncing with cloud..."
- **Playful:** "Gathering pixels...", "Brewing your dashboard...", "Almost there!"
- **Professional:** "Preparing your report...", "Verifying details..."

### Branded Animations (Lottie/SVG)
For significant loading moments (initial app boot, complex data processing), replace the standard spinner with a small, brand-specific animation.
- A designer's tool might show a pencil drawing a line.
- A fitness app might show a pulsing heart or a moving runner icon.
- A financial tool might show coins stacking or a chart line moving upward.

### Progressive Storytelling
If a wait is consistently long (3s+), use the loading area to tell a small story or provide value:
- **Tips & Tricks:** "Did you know you can use Ctrl+K to search?"
- **Process Transparency:** Show what the system is doing: "Checking database..." → "Optimising results..." → "Finalising view..."

### Visual Transitions (Arrival)

When transitioning from a loading state to content, use a crisp fade-in (150ms) to make the arrival feel like a reward. Avoid scaling the incoming content, as it can cause layout instability.

---

## Review Checklist

- [ ] Is the loading state appropriate for the expected wait duration (spinner vs skeleton)?
- [ ] Does the skeleton screen match the physical layout of the incoming content?
- [ ] Is there a subtle shimmer animation on skeletons to signal "active loading"?
- [ ] Are buttons disabled during loading to prevent duplicate actions?
- [ ] Does content fade in over skeletons (150–200ms) rather than blinking into existence?
- [ ] For full-page loads, is a staggered entry used to guide the eye?
- [ ] Is `prefers-reduced-motion` respected for all loading animations?
- [ ] In "Optimistic UI" moments, is there a clear rollback path if the action fails?
- [ ] Does content load in priority order (highest-value first, rest streaming in), fetching only what the current view needs rather than everything up front?
- [ ] Where the next step is predictable, is it prefetched so it feels instant — without speculatively loading everything?

## Common Anti-Patterns

| Anti-pattern | Problem | Fix |
|---|---|---|
| A global spinner that blocks the whole app | High frustration, user cannot browse other areas | Use contextual loaders or skeletons |
| Skeletons that don't match the final layout | Massive layout shift (CLS) when data arrives | Match shapes and sizes exactly |
| Too many spinners on one page | Visual noise, feels like the whole app is broken | Group loading states into a single container skeleton |
| Faster-than-light skeletons | Shimmer animation that is too fast or high-contrast | Keep shimmer slow (1.5s+) and very subtle |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.