Loading States in Mobile Apps: Spinners vs Skeletons
When to Use Each Pattern, How Long Users Will Tolerate the Wait, and the iOS + Android Implementations
Every mobile app has loading moments. The question is not whether to show one, but which kind to show. Spinners feel slower than they actually are. Skeleton screens feel faster than they actually are. Progress bars work for some operations and break for others. This guide breaks down the differences and shows you exactly when to use each pattern. If you also need empty state guidance, our app empty states guide covers the next state after loading.
What You Will Learn
- The 4 main loading state types and when to use each
- How long users will wait before perceiving an app as broken
- Why skeleton screens feel faster even at the same actual speed
- The 6 loading state mistakes that frustrate users
Backed by Apple Human Interface Guidelines, Google Material Design, and patterns we see across 10 million+ apps built on Appy Pie AI. Rated 4.7/5 on G2 from 1,388 reviews.
Build an App With Smart Loading StatesTL;DR Quick Summary
Use skeleton screens for content-heavy screens (feeds, profiles, lists). Use spinners for short backend operations under 2 seconds. Use progress bars when you can measure progress accurately. Use shimmer effects when fetching media-rich content. Whatever you pick, never show nothing; the worst loading state is no loading state at all.
Table of Contents
Jump to any section. This guide compares spinners vs skeletons, breaks down the 4 main loading types, shows industry-specific patterns, and reveals the mistakes that hurt UX.
- Why Loading States Decide Retention
- Spinners vs Skeletons: The Full Comparison
- The 4 Types of Loading States
- Loading Time Benchmarks Users Will Tolerate
- Industry Loading Patterns: 6 Verticals
- iOS vs Android Implementation
- 6 Loading State Mistakes That Frustrate Users
- How Appy Pie AI Handles Loading States
- Frequently Asked Questions
- Conclusion
Why Loading States Decide Retention
Mobile apps are full of waiting moments. Backend calls, image downloads, search queries, login flows, payment processing. Every one of these moments has a fraction of a second to a few seconds where the app must signal “I am working” before users assume something is broken.
What Loading States Have to Accomplish
- Signal that the app is responsive: Confirm the tap registered immediately
- Communicate progress when possible: Tell users where they are in the wait
- Set expectations for duration: Hint at how long this will take
- Reduce perceived wait time: The right pattern can make 3 seconds feel like 1
- Prevent re-tapping: Disable buttons during async operations
Loading states are the connective tissue between every screen in your app. We covered the screens themselves in our app navigation patterns guide and the moments before content in our app empty states guide.
Spinners vs Skeletons: The Full Comparison
The two most common loading patterns serve very different purposes. Pick wrong and your app feels slower than competitors with the same actual speed.
SpinnerUSE SPARINGLY
- Best for: Short operations under 2 seconds
- Examples: Login submit, save action, payment confirm
- User tolerance: Up to 5 seconds before frustration kicks in
- Perceived speed: Slow (feels like the app is stuck)
- Best placement: On the button itself, replacing the label
- Avoid: Full-screen spinners that block all interaction
Skeleton ScreenPREFER THIS
- Best for: Content-heavy screens (feeds, profiles, lists)
- Examples: News feed, product list, message thread loading
- User tolerance: Up to 11 seconds before frustration
- Perceived speed: Fast (feels like content is arriving)
- Best placement: Inline, where the real content will appear
- Avoid: Showing skeletons for buttons or small UI elements
The 4 Types of Loading States
Beyond spinners and skeletons, two other patterns serve specific cases. Knowing all 4 lets you pick the right pattern for every situation.
Spinner
Indeterminate rotation. Good for short waits. Use on buttons during async actions.
Skeleton Screen
Gray placeholder that mirrors final content shape. Best for content-heavy screens.
Progress Bar
Use only when you can measure actual progress. Bad if it stalls or jumps.
Shimmer Effect
Animated gradient over placeholder shapes. Used by Facebook, LinkedIn for feeds.
Loading Time Benchmarks Users Will Tolerate
Users have measurable patience thresholds for loading. Knowing them lets you pick the right pattern for the expected wait time.
| Wait Time | User Reaction | Recommended Pattern |
|---|---|---|
| 0 to 1 second | Feels instant. No loading state needed | None (or button state change) |
| 1 to 2 seconds | Slight pause but still feels responsive | Button spinner |
| 2 to 4 seconds | Conscious wait. Users want feedback | Inline skeleton or button spinner |
| 4 to 10 seconds | Frustration starts. Need clear progress signal | Skeleton with shimmer, or progress bar |
| 10+ seconds | Most users abandon. Reconsider the operation | Background process + push notification when done |
Industry Loading Patterns: 6 Verticals
Different app categories have different loading expectations. Match your loading state to what the category trained users to expect.
Skeleton menu cards
Users expect to scroll a menu fast. Skeleton cards in menu shape signal “menu is loading” instead of “app is broken.”
Skeleton + shimmerSkeleton rails + spinner
Skeleton for content rows while loading. Spinner over the video player during buffering. Mix patterns by zone.
Skeleton + spinnerSkeleton product grid
Product cards in skeleton form. Image areas show shimmer until photos load. Critical for category browsing.
Skeleton + shimmerSpinner + progress bar
Banking apps prioritize accuracy signals. Use progress bars for transactions. Spinner on confirm actions. Avoid skeleton (too playful).
Spinner + progressProgress bar + animation
Travel searches take time. Use a progress bar plus an illustration to keep users engaged during 5 to 15 second searches.
Progress bar + illustrationiOS vs Android Implementation
Both platforms provide native loading components but they differ in defaults, conventions, and best practices. Use the platform-native approach when possible.
| Pattern | iOS | Android |
|---|---|---|
| Spinner | UIActivityIndicatorView | CircularProgressIndicator |
| Progress Bar | UIProgressView | LinearProgressIndicator |
| Pull to refresh | UIRefreshControl (built-in) | SwipeRefreshLayout |
| Skeleton screens | Custom (no native) | Custom (no native, but Shimmer library popular) |
| Loading delay | Show after 300ms | Show after 300ms |
The 300ms Rule
If a loading state would only be visible for less than 300 milliseconds, do not show it. Quick flashes of spinners feel like glitches. Hold the state until you are sure the operation will take 300ms or more. Most modern UI frameworks support this delay natively.
Native vs Custom Loading States
- Use native when: short operations, system actions, common patterns
- Use custom when: brand consistency matters, skeleton screens, long content loads
- Hybrid: Native spinners on buttons + custom skeletons on screens. This is the most common production pattern
6 Loading State Mistakes That Frustrate Users
These are the loading state issues we see most often in apps that get “feels slow” complaints despite normal performance.
1. Full-screen spinners for long operations
A full-screen spinner blocks all interaction and feels broken at 3+ seconds. Replace with inline skeleton screens that let users see the page structure forming.
2. No loading state at all
The worst loading pattern is silence. Users assume the app is frozen or broken. Always show some indicator within 100ms of any user action.
3. Showing loading states for instant operations
Operations under 300ms should not show a loading state. The brief flash feels like a glitch. Either hold the state for at least 400ms or skip it entirely.
4. Progress bars that lie
A progress bar that jumps from 30% to 90% then sits at 90% is worse than a spinner. Only use progress bars when you can measure real progress.
5. Skeleton screens that look nothing like the final content
If the skeleton shows three rectangular bars but the content is a grid of product cards, the transition feels jarring. The skeleton must mirror the content shape.
6. Never allowing cancellation
Long operations should let users cancel. A loading state without an escape feels like a hostage situation. Add a “Cancel” link to operations over 5 seconds.
How Appy Pie AI Handles Loading States
If you build with Appy Pie AI AI App Generator, the platform applies smart loading state defaults. Native spinners on buttons. Skeleton screens for content lists. Progress indicators for known-duration operations. All customizable from the editor.
What this looks like in practice
The Appy Pie AI builder itself demonstrates good loading state patterns. When you submit your app description, the system shows clear feedback that work is happening. The transitions between steps are smooth.

When users submit their app name to the AI builder, the response feels nearly instant because the system processes quickly but also shows a brief acknowledgment before the next question appears.

After submission, the system shows confirmation while processing. The brief loading moment is filled with confirmation feedback rather than a stark spinner alone.

When the AI has gathered enough context, it confirms understanding before beginning to build. This communicates progress between two distinct phases of the operation.

Once the app is fully generated, the editor opens with all content populated. The transition from “generating” to “ready” is clear; users never wonder whether the process is complete.

How a real Appy Pie AI customer uses loading states
DO Max in the Netherlands runs entertainment app with movies, live TV, and games. Their app uses skeleton screens for content rows so users feel the catalog arriving as they browse. Combined with push notifications for re-engagement, the app saw a 28% increase in average session duration. Smart loading states contributed to that engagement lift.
Frequently Asked Questions About Loading States
When should I use a spinner vs a skeleton screen?
Use spinners for short operations under 2 seconds, typically on buttons (login submit, save, payment confirm). Use skeleton screens for content-heavy screens that take 2 or more seconds (feeds, product lists, profiles). The rule of thumb: if the final result is a list of items in a known shape, use a skeleton.
How long will users wait before abandoning a loading screen?
The thresholds: 1 second feels instant, 3 seconds creates conscious frustration, 5 seconds causes most users to consider leaving, 10 seconds causes the majority to abandon. Skeleton screens with shimmer extend tolerance significantly compared to plain spinners.
What is a shimmer effect?
A shimmer is an animated gradient that moves across skeleton placeholder shapes, suggesting content is on its way. Facebook popularized the pattern in 2014. It signals “active loading” without being as jarring as a rotating spinner.
Should I show a loading state for operations under 1 second?
No. Operations under 300 milliseconds should not show a loading state at all. The brief flash feels like a glitch. Operations between 300ms and 1 second should show a subtle button state change but not a full spinner.
What is the difference between a progress bar and a spinner?
A progress bar shows measurable progress (40%, 75%, 100%). A spinner shows that something is happening without measuring how much is done. Use a progress bar only when you can accurately measure progress; otherwise use a spinner or skeleton.
Why do skeleton screens feel faster than spinners?
Skeleton screens hint at what is coming. Users mentally start processing the layout before content arrives. Spinners give no preview, so users wait passively. The same actual load time feels roughly 2x faster with skeletons compared to spinners.
Can I use multiple loading patterns in the same screen?
Yes, and the best apps do. A typical screen might use a skeleton for the content area, a spinner on a refresh button, and a progress bar for an upload happening in the background. Match each loading pattern to its specific operation.
What is the 300ms rule?
If a loading state would be visible for less than 300 milliseconds, do not show it. Brief flashes of spinners feel like glitches. Either hold the state for at least 400ms or skip it entirely.
How do I implement skeleton screens?
iOS and Android do not have native skeleton components, but third-party libraries like Shimmer for Android and SkeletonView for iOS make it straightforward. Many no-code platforms like Appy Pie AI apply skeleton patterns automatically for list-based content.
What is the most common loading state mistake?
Showing a full-screen spinner for a long operation. Users feel blocked and assume the app is broken. The fix is to use a skeleton screen inline where the content will appear, so users can see the page structure forming. For more app design topics, see our app empty states guide and app navigation patterns guide.
Build an App With Smart Loading States
Skip the loading state debate. Appy Pie AI applies skeleton screens, spinners, and progress bars where they fit best, automatically.
Try App BuilderAI App GeneratorPerceived Speed Beats Actual Speed.
The fundamentals are simple. Use skeleton screens for content-heavy screens. Use spinners for short backend actions. Use progress bars only when you can measure progress. Never show nothing. Never show a loading state for operations under 300 milliseconds. Match the pattern to your category and to the expected wait time. Skeleton screens can make your app feel 2x faster than spinners at the same actual speed. Build smarter with our complete app creation guide or check our app empty states guide for what shows after loading completes.
Start Building Your App →