Defer the spinner
Wait ~300ms before a spinner, then keep it up at least 500ms.
Guillermo Rauch7 Principles of Rich Web ApplicationsBut even in those cases, the display of spinners or loading indicators should be deferred. They should only be rendered after the user no longer considers the response was immediate.
Guillermo Rauch7 Principles of Rich Web ApplicationsI contend that spinners or "loading indicators" should become a rarity
Demo 2 plots Jakob Nielsen's response-time limits, which the essay quotes.
1 · Same click, four speeds
Pick a response time above, then refresh both cards.
Server answers in 300ms
Spinner at onceBad
Deferred, held 500msGood
function useDelayedPending(pending, { delay = 300, minDuration = 500 } = {}) {
const [show, setShow] = useState(false);
const since = useRef(0);
useEffect(() => {
if (pending && !show) { // wait before showing anything
const t = setTimeout(() => { since.current = Date.now(); setShow(true); }, delay);
return () => clearTimeout(t);
}
if (!pending && show) { // once shown, never blink
const left = minDuration - (Date.now() - since.current);
const t = setTimeout(() => setShow(false), Math.max(0, left));
return () => clearTimeout(t);
}
}, [pending, show, delay, minDuration]);
return show;
}
2 · What's on screen at time t
Drag the response time and the playhead, or press Play.
Timeline0 – 3s
Nothing newSpinnerResultBlink under 400ms0.1s and 1s limits
“0.1 second is about the limit for having the user feel that the system is reacting instantaneously, meaning that no special feedback is necessary except to display the result.”
Why it matters, pros and cons
Why it matters
A fast answer needs no feedback but the result. A spinner that blinks for 150ms reads as a glitch, not progress.
Pros
- Fast responses look instant instead of glitchy.
- Spinners turn rare, so when one shows it means something.
- The minimum hold kills the blink-then-content flicker.
Cons
- Slow paths get feedback 300ms later: keep the press state.
- The hold can delay a ready result by up to 500ms.
- Tune per surface: a page can wait longer than a Save.