Stop Using a Loading Spinner (2017)
blog.iamsuleiman.com
blog.iamsuleiman.com
With no theories to back this up whatsoever, here's my completely unsubstantiated gold-standard strategy for loading states:
1. Make it fast. Most of the examples are loading content. Is there any reason you need more than 100ms to do that? Buy a bigger database server and use a CDN/Edge. Prefetch some content. Unlike fancy skeleton designs, this is worth obsessing over and spending money on. Why "trick" users when you can just perform so well you don't have to.
2. Instantly give inline feedback that an action was started. Could be a spinner on the button, text below the button, a toast / non-modal overlay, a loading indicator in the top right... If you get your response in 100ms, you don't really need this, but the network could always be slow etc.
3. Wait some time (something like 1 second imho) to see if you can transition to new finished state
4. If the full transition can't happen in the timeout, transition to a full loading state. I don't think it even matters that much what kind. Could be a spinner screen, a skeleton screen. No modal overlays though unless a destructive/uninterruptible action like a booking or payment is taking place.
5. Show an indicator/overlay if network quality is bad. The user will not blame it on you and have no expectations for your app to behave particularly well.
Of course if you can just make a fast loading website, let the browser handle the transitions. It's already a fine loading experience.
This really needs to be the go-to. We're too accepting of delay these days.
Skeletons are just another big, flashy indeterminate loading bar. They feel slightly faster because you can get a feel for the content layout, but only as long as the size and behaviour perfectly matches the loaded content. Usually they don't, and the entire screen reflow six times before all the skeletons are loaded in, which take up more precious data to slow down the important parts of your application as well. Most of the time they feel slower because you're actively being tricked as a user by the "almost there" page layout. They're an indeterminate loading spinner in disguise.
If you want to make your code feel faster, show your users that something is happening. Give them actual, real progress bars. Fill up a bar somewhere as content comes streaming in from your myriad of endpoints and unnecessary tracking libraries. Focus on shaving down your load times instead of optimizing the way you show them! Do you really need those four JSON calls to load data that could've been in the HTML the first time?
The design problem that gets overlooked is how to inform users that things are taking longer than normal. Even the eventual fail message with "try again later" is often worded and designed without much consistency.
If the website or app consistently violates this, then it is time for a different design.
But more often than not the "Good enough, ship it" wins out and the user experience is suffering.
I can understand that time to market and maximizing profit is important, but at the second version the expectation is that it is improved.
Google was very aware of this with their search engine, so these things matter.
My personal least favourite example ever is Windows Explorer when it's trying to connect to a network share that isn't there. It looks like an actual progress bar until you realise that it's only asymptotically approaching "done."
I instinctively interpret them as an app that started allowing interaction before fully loading. Is something horrible going to happen if I click something before it fully loads? Do I even know when it fully loads?
Think of loading glitches in a 3D game -- you open a door and half the world is missing on the other side because the assets aren't there yet. You might fall through the floor if you try walking. Or maybe not.
This only work if the website isn't a bloated single page app.
But now that I think about it, I also see them for payment forms, where the loading time is usually short. Thinking more about it, I think they annoy me because they fake having loaded something useful. But there is no interaction yet, nothing I can do. A spinner is truthful, a skeleton is a lie. Interesting, I had never thought about this before ;)
Users want speed, using a spinner or a skeleton won't fix a slow response. The best approach is to CDN everything possible, locally cache everything possible, and show a simple spinner IMO. Spinners are just there to say "wait, please, something is happening". The response time needs to be reasonable, that's all. Users aren't dumb and they know a skeleton is only a (dishonest?) illusion
Because just look at HN itself; a comments page is a long list of content, not dissimilar to the examples given of Facebook, but it loads instantly with only a small spinner in the tab bar that resolves in less than 200ms. No skeletons or spinners are actually needed on the page itself.
I'm convinced that most sites would work faster if the pages are just rendered server-side. I don't believe it would cost more server load, and I don't believe the extra server side cost, if any, outweighs the vastly improved client performance. Plus it can be scaled, especially with modern-day techniques like CDN workers / lambdas; they could put the templates and final rendering into those edges, close to the end user, and only pass data between their datacenters and the CDN's edges. From there on out they could make the pages partially dynamic.
Then there's the error in the other direction - the button you push which has no visual indication that it's been pushed and takes a long time to do something. Those used to come with warnings "Don't push the button twice, or you'll be charged twice." Worst example today is here: [1] Fill out the form. Wait. Wait some more. After about 30 seconds, get "Application error: a client-side exception has occurred (see the browser console for more information)." In the the error console, there is the error "Minified React Error #31". Very helpful.
> Most of all, it makes people perceive your site to be faster than it actually is. Remember that we are designing interfaces for use by real people. We need to give people the illusion of speed.
The first claim is not backed up by evidence? At least not in this article and the claim "we need to give people the illusion of speed" makes no sense?
And then for the perceived benefits of skeleton loading screens.
> 1. Helps people perceive your screen to load faster
Again 1. is just an assumption for all I can tell, you don't cite any research on this.
> 2. Eliminates surprises
As for 2, with skeleton screens there is still pretty much always a significant layout shift as it is quite uncommon for all elements to have pre-defined dimensions so the skeleton screen actual works. So it can work for some screens. But if you implement it only for some screens, users will be surprised about the differences. Hence, user is surprised? :D
> 3. Gradual loading of UI – clear indication of progress
As for 3, there is literally no difference in the indication of progress between this and a spinner.
> 4. Shows exactly what’s loaded and what’s yet to load
As for 4, see 2.
;)
I don't see much difference between them. A skeleton loader is functionally a spinner that in a clear way reserves the space for the component being loaded.
Skeletons are less clear because broken or missing things on a page can sometimes look like skeletons. Loading spinners never look broken or ambiguous.
I don't think it really matters. Skeletons might be better for the type of layout, and loading spinners shouldn't be overused. Skeletons shouldn't be overused either.
The article is strongly opinionated that loading spinners are just bad full stop. I doubt that claim. They are universally recognised even more than hamburger menu icons.
Seriously, why is it so bad to tell a user what the hell they are waiting for? Sure, it will be gibberish to some users, but even they will understand that your code is trying to do something.
Even better, have a time check with a head's up that something is taking longer than expected.
- If you don't stream HTML directly, you can use the streaming API (browser native).
- If you use one of the above techniques you can show a progress bar on top of it.
- Alternatively count the things you fetch and drive a progress bar out of that.
- If you have a single request and one big thing you fetch (typical for backend for frontend pattern) then you might roughly know how long it should take.
- You can add some currently known quantity to your heuristic to determine estimates.
- You can alert the user with "takes longer than expected" messages and clearly communicate the implications of a reload.
Special mention for animated skeletons. (please leave my CPUs alone, you aren't going to stop the animation if the loading hangs anyway, because you assume everything is going to be as expected, so the animation means nothing and I lost confidence in it)
If all you need to cover is just the content loading sequence, why not use the proper progress bar? Nowadays when we have HTTP/2 and don't have to bundle all the calls together anymore, your code can learn ahead how many content blocks it has to load in a certain layout, so it's not that hard to automate it to update the progress bar accordingly. Although I'd frankly always prefer the endless animated spinner to having the progress bar get stuck at 99% in the glorious Win98 style...
1. When you looked at the Loading Spinner, did you know how much time remains to complete?
2. How much of the content has loaded?
3. How much remains to load?
You don't know how much time loading your data will take, you don't know how much of it has been loaded and how much remains, at least most of the time. You probably aren't going to spend a bunch of resources on adding information about the sizes of all of your API endpoints (or even averages if you can't do per-request), aggregating all of the endpoints that might need to be hit for some component to be displayed and visualizing it.Most of the time, even the loading spinners can be an afterthought in the face of needing to implement whatever the business requirements are. That's also why the fake loading bars that get slower towards the end were popular for a while.
In my mind, use whatever is easy and feels good to you; spinners, loading bars or even skeletons. Don't just leave your users hanging with no visual feedback. The rest is just details.
A countdown is better, but not all tasks can be subdivided easily to allow for monitoring.
In such cases, I like to use a pop-up window that says something like "Doing X. This may take a minute or so". This tells the user that they shouldn't bother staring at the app, and can do something else for a while. Usually that sort of information is all that's needed. "an hour" means time to work on something else. "a day" means write a postit note to check tomorrow afternoon. Etc.
Skeleton UIs need to replicate and be kept in sync with your real UI implementation, progressively loaded images usually requires some server side pre-processing of the images and storing metadata, and calculating + receiving accurate server progress updates isn't trivial when the progress depends on unpredictable algorithms and multiple services.
I didn't see any loading spinner - just loads of whitespace. I have Javascript disabled, and I'm not going to enable it for some random blog.
For things that require actually waiting, prefer progress bar first and basic spinner when it's not practical.
That and working out why a plugin was failing and stating that "There's no init in it, innit". Skill. Savour these moments.
If you click on something that is AJAX-y, you need to provide feedback that yes, you clicked something and yes, the app is processing your request.
The first case I would just make your page load faster. The second case I think a spinner is perfect.