From 6ccf642ac1d16be73af889968c82bafedab5bc69 Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sat, 25 Apr 2026 20:19:48 -0400 Subject: [PATCH 1/8] Add Do Not Use Spinners pattern Closes #6 Co-Authored-By: Claude Opus 4.7 (1M context) --- src/patterns/dont_use_spinners.md | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/patterns/dont_use_spinners.md diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md new file mode 100644 index 0000000..a37f606 --- /dev/null +++ b/src/patterns/dont_use_spinners.md @@ -0,0 +1,82 @@ +--- +layout: article.njk +title: Don't Use Spinners +tags: pattern +thumbnail: /assets/no_spinners.svg +og_image: /assets/speed_patterns_og_image.jpg +order: 9 +--- + +The animated circular spinner has become the default progress indicator on the web. It's also the wrong tool in nearly every case it's used. Spinners communicate almost no useful information, and their default presence often signals that no thought was given to how the experience handles waiting at all. + + + +
+
The classic spinner: an animation that says nothing.
+Animated circular spinner with a slash through it +
+ +## What's Wrong With Spinners? + +A spinner is a circle without a beginning or an end. It rotates indefinitely, resetting every time it completes a turn. As a piece of communication, this has several specific failures: + +- **No start, no end, no progress.** The user can't tell whether the operation is 10% complete or 90% complete — only that something is, in some sense, happening. +- **The motion lies about activity.** A spinner can keep rotating cheerfully even when the underlying request has hung. The animation is decoupled from any real signal. +- **It tells the user nothing about what is being loaded.** The same spinner appears for "submitting your order," "loading your photos," and "fetching the next 25 results" — three operations with very different stakes. +- **It admits failure.** A spinner is the developer telling the user, "this part of the site is slow and I don't have a better idea." It is, at best, an apology. + +Linear (bar-shaped) indeterminate indicators have most of the same problems — they're slightly less visually grating, but they communicate equally little. + +## Solution + +Treat the absence of progress as a design problem to solve, not a hole to plug with a stock animation. The right approach depends on what's actually happening behind the wait. + +### 1. Make the wait shorter + +Most spinner appearances would be unnecessary if the underlying operation were faster. Before designing for a wait, investigate whether the wait can be removed: + +- Can the data be prefetched, cached, or rendered server-side? +- Can the response be streamed so the user sees something immediately? +- Can the action be performed optimistically, with rollback on failure? + +A spinner used as the first response to "this is slow" tends to harden the slowness in place — once a spinner is in the codebase, the slow path is no longer a bug. + +### 2. Use a structural placeholder + +For loading content into a region of the page, use a [skeletal design](/patterns/skeletal_designs/) that mirrors the final layout. Skeletal placeholders convey: + +- **What the content will be** (zones, headings, image positions). +- **Where to look** when the content arrives. +- **The structure of the page**, so the user can begin orienting themselves. + +A spinner conveys none of this. Skeletal designs do all of it for almost the same implementation cost. + +### 3. Acknowledge the action specifically + +For form submissions and discrete user actions, a spinner is the wrong shape of feedback. The right pattern is to [acknowledge the action](/patterns/acknowledge_actions/) directly: disable the trigger, change its label to describe what's happening, and confirm completion when the action lands. + +### 4. Use motion to bridge the gap + +For unavoidable transitions, [mask slowness with animation](/patterns/masking_slowness_with_animation/). A short, purposeful transition that takes the user from the old state toward the new one absorbs a meaningful amount of the wait, and tells the user exactly what's happening — unlike a spinner, which exists outside the actual content flow. + +### 5. Show real progress when you have it + +If the operation has a known duration or measurable progress (file upload, multi-step form, batch operation), use a real progress bar with percentage and, where possible, a description of the current step. This is the only place where a literal progress indicator earns its space on the screen. + +## When (Rarely) a Spinner Is OK + +There are a few cases where a small inline spinner is acceptable: very short waits inside a button or input where structural placeholders would be overkill, or genuinely indeterminate background tasks where the user has explicitly opted in. Even there, prefer a tiny, subtle indicator next to the relevant element — never a full-page overlay spinner, which holds the entire UI hostage. + +## Why This Matters + +Defaulting to a spinner is rarely a deliberate choice — it's a fallback that gets reached for when no one has thought through the loading experience. Making "no spinners" a team norm forces that conversation to happen earlier, which usually surfaces a better solution: faster code, better placeholders, clearer feedback, or all three. + +## Related Patterns + +- [Skeletal Designs](/patterns/skeletal_designs/) — structural placeholders that actually communicate. +- [Acknowledge Actions](/patterns/acknowledge_actions/) — feedback for discrete user actions. +- [Masking Slowness With Animation](/patterns/masking_slowness_with_animation/) — using transitions to absorb unavoidable delay. + +## Resources + +- [Mobile Design Details: Avoid The Spinner](https://www.lukew.com/ff/entry.asp?1797) by [Luke Wroblewski](https://lukew.com/) From 299b9e38a076795d7ecb35c8d65f9fa4857c8619 Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sun, 26 Apr 2026 12:37:22 -0400 Subject: [PATCH 2/8] Drop trailing periods from list items --- src/patterns/dont_use_spinners.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md index a37f606..37ebd0e 100644 --- a/src/patterns/dont_use_spinners.md +++ b/src/patterns/dont_use_spinners.md @@ -20,10 +20,10 @@ The animated circular spinner has become the default progress indicator on the w A spinner is a circle without a beginning or an end. It rotates indefinitely, resetting every time it completes a turn. As a piece of communication, this has several specific failures: -- **No start, no end, no progress.** The user can't tell whether the operation is 10% complete or 90% complete — only that something is, in some sense, happening. -- **The motion lies about activity.** A spinner can keep rotating cheerfully even when the underlying request has hung. The animation is decoupled from any real signal. -- **It tells the user nothing about what is being loaded.** The same spinner appears for "submitting your order," "loading your photos," and "fetching the next 25 results" — three operations with very different stakes. -- **It admits failure.** A spinner is the developer telling the user, "this part of the site is slow and I don't have a better idea." It is, at best, an apology. +- **No start, no end, no progress.** The user can't tell whether the operation is 10% complete or 90% complete — only that something is, in some sense, happening +- **The motion lies about activity.** A spinner can keep rotating cheerfully even when the underlying request has hung. The animation is decoupled from any real signal +- **It tells the user nothing about what is being loaded.** The same spinner appears for "submitting your order," "loading your photos," and "fetching the next 25 results" — three operations with very different stakes +- **It admits failure.** A spinner is the developer telling the user, "this part of the site is slow and I don't have a better idea." It is, at best, an apology Linear (bar-shaped) indeterminate indicators have most of the same problems — they're slightly less visually grating, but they communicate equally little. @@ -45,9 +45,9 @@ A spinner used as the first response to "this is slow" tends to harden the slown For loading content into a region of the page, use a [skeletal design](/patterns/skeletal_designs/) that mirrors the final layout. Skeletal placeholders convey: -- **What the content will be** (zones, headings, image positions). -- **Where to look** when the content arrives. -- **The structure of the page**, so the user can begin orienting themselves. +- **What the content will be** (zones, headings, image positions) +- **Where to look** when the content arrives +- **The structure of the page**, so the user can begin orienting themselves A spinner conveys none of this. Skeletal designs do all of it for almost the same implementation cost. @@ -73,9 +73,9 @@ Defaulting to a spinner is rarely a deliberate choice — it's a fallback that g ## Related Patterns -- [Skeletal Designs](/patterns/skeletal_designs/) — structural placeholders that actually communicate. -- [Acknowledge Actions](/patterns/acknowledge_actions/) — feedback for discrete user actions. -- [Masking Slowness With Animation](/patterns/masking_slowness_with_animation/) — using transitions to absorb unavoidable delay. +- [Skeletal Designs](/patterns/skeletal_designs/) — structural placeholders that actually communicate +- [Acknowledge Actions](/patterns/acknowledge_actions/) — feedback for discrete user actions +- [Masking Slowness With Animation](/patterns/masking_slowness_with_animation/) — using transitions to absorb unavoidable delay ## Resources From 2526cf658578ac127a99bd60d7693381b48639ea Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sun, 26 Apr 2026 13:36:45 -0400 Subject: [PATCH 3/8] Convert figcaption to paragraph; add 'Don't use Spinners!' caption below image --- src/patterns/dont_use_spinners.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md index 37ebd0e..00e83f3 100644 --- a/src/patterns/dont_use_spinners.md +++ b/src/patterns/dont_use_spinners.md @@ -11,9 +11,11 @@ The animated circular spinner has become the default progress indicator on the w +The classic spinner: an animation that says nothing. +
-
The classic spinner: an animation that says nothing.
Animated circular spinner with a slash through it +
Don't use Spinners!
## What's Wrong With Spinners? From 5a160cd2d91e47601f3fe9d35e1e8bf515b6c7c4 Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sun, 26 Apr 2026 13:41:43 -0400 Subject: [PATCH 4/8] Double spinner illustration size --- src/patterns/dont_use_spinners.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md index 00e83f3..4a9340f 100644 --- a/src/patterns/dont_use_spinners.md +++ b/src/patterns/dont_use_spinners.md @@ -14,7 +14,7 @@ The animated circular spinner has become the default progress indicator on the w The classic spinner: an animation that says nothing.
-Animated circular spinner with a slash through it +Animated circular spinner with a slash through it
Don't use Spinners!
From 990537fe83d7b028260057205b107b3b185d4bcf Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sun, 26 Apr 2026 14:03:02 -0400 Subject: [PATCH 5/8] Add 1rem margin around spinner illustration --- src/patterns/dont_use_spinners.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md index 4a9340f..2779ae7 100644 --- a/src/patterns/dont_use_spinners.md +++ b/src/patterns/dont_use_spinners.md @@ -14,7 +14,7 @@ The animated circular spinner has become the default progress indicator on the w The classic spinner: an animation that says nothing.
-Animated circular spinner with a slash through it +Animated circular spinner with a slash through it
Don't use Spinners!
From 9b19301425403c9ce875322cd3cb4ed8751e7906 Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sun, 26 Apr 2026 14:06:21 -0400 Subject: [PATCH 6/8] Use vertical-only margin so global figure rule keeps centering --- src/patterns/dont_use_spinners.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md index 2779ae7..c6889cf 100644 --- a/src/patterns/dont_use_spinners.md +++ b/src/patterns/dont_use_spinners.md @@ -14,7 +14,7 @@ The animated circular spinner has become the default progress indicator on the w The classic spinner: an animation that says nothing.
-Animated circular spinner with a slash through it +Animated circular spinner with a slash through it
Don't use Spinners!
From 9a03f20735501b84880621e72891d753b32f88ed Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sun, 26 Apr 2026 20:30:03 -0400 Subject: [PATCH 7/8] Add author and creation date to Dont Use Spinners Author taken from the original issue (#6) creator; date is the issue creation date. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/patterns/dont_use_spinners.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md index c6889cf..1f4331b 100644 --- a/src/patterns/dont_use_spinners.md +++ b/src/patterns/dont_use_spinners.md @@ -5,6 +5,10 @@ tags: pattern thumbnail: /assets/no_spinners.svg og_image: /assets/speed_patterns_og_image.jpg order: 9 +date: 2017-12-05 +authors: + - name: Sergey Chernyshev + url: https://www.sergeychernyshev.com/ --- The animated circular spinner has become the default progress indicator on the web. It's also the wrong tool in nearly every case it's used. Spinners communicate almost no useful information, and their default presence often signals that no thought was given to how the experience handles waiting at all. From 712883f9aeb43778459cb4d8978dc3de879ce666 Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Sun, 26 Apr 2026 20:40:19 -0400 Subject: [PATCH 8/8] Mark Do Not Use Spinners as AI-assisted Co-Authored-By: Claude Opus 4.7 (1M context) --- src/patterns/dont_use_spinners.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/patterns/dont_use_spinners.md b/src/patterns/dont_use_spinners.md index 1f4331b..5c028ed 100644 --- a/src/patterns/dont_use_spinners.md +++ b/src/patterns/dont_use_spinners.md @@ -5,6 +5,7 @@ tags: pattern thumbnail: /assets/no_spinners.svg og_image: /assets/speed_patterns_og_image.jpg order: 9 +ai_assisted: true date: 2017-12-05 authors: - name: Sergey Chernyshev