Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Stop Using a Loading Spinner (2017) (iamsuleiman.com)
57 points by zeroday28 on May 2, 2022 | hide | past | favorite | 49 comments


I have no love for skeletons. They feel clever at first, but as a user, I associate nothing but bad experiences with them. I feel the same way about PWA app shells.

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.


> Make it fast.

This really needs to be the go-to. We're too accepting of delay these days.


Agree, Outlook.com has been worse then before, its freaking bad.


Everything in this post is better advice than anything in the article.


Indeterminate loading spinners suck. You're only supposed to use them when you don't know how long something is going to take, for example when you're setting up a socket to a remote server. After that, you're not supposed to use indeterminate spinners anymore.

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?


To me, an indeterminate spinner says very clearly: no idea how long this may take. Progress bars provide more information, but might be at least as misleading as a spinner. My Netflix app typically loads a movie like this: 0% ... 34% ... 99% ... 99% ... 99% ... 99% ... 99% ... play, although sometimes it does: 0% ... 1% ... 2% ... 2% ... 54% ... play. Fortunately, the netflix progress indicator keeps spinning, so you sort of know that it's to be expected. If it were an unanimated progress bar, I would start suspecting an error when it gets stuck (as it routinely does).


Agree, being stuck on 99% is worse than stuck on a loading spinner.

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.


Ideally no percentage increase should take more than maybe 10-15% of the total time.

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.


To take this a step further, "progress indicators" suck when they don't actually give you any indication of how much progress is being made.

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."


It might be just me, but skeletons give me an unsettling feeling.

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.


A good skeleton UI should not stop you to interact with the page. You should be able to click on the image placeholder to direct you to the related page.

This only work if the website isn't a bloated single page app.


It’s probably psychological, but I always perceive skeletons as slow. Maybe because mainly slow-loading sites like new reddit or facebook use them?

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 ;)


I kind of bought into skeletons as a dev - because of the hype - but mercilessly purged my created skeletons later because as a user I saw that they were just as annoying if not more than spinners.

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


And don't use custom fonts. Google's pages are much slower because of those.


I mean skeletons - as well as spinners - are a patch on the real issue, that it takes time to load a page.

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.


Maybe you are old enough to remember when connections were so slow that pages loaded one line of an image at a time and gave you the skeleton effect for free?


Skeletons make the site look broken


Fully agree. A slow skeleton page is worse than a slow spinner. Neither are good. Give me simple HTML!


All that progressive loading is built into browsers and occurs by default. Unless you take control of loading away from the browser's defaults with too much Javascript and back and forth with the server.

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.

[1] https://otherside.xyz/sdk


This article is very frustrating, it's full of assumptions that are stated as facts.

> 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.


Here's someone who did some research and found the exact opposite to be true for example https://www.viget.com/articles/a-bone-to-pick-with-skeleton-...


Please continue using "loading spinners", as they are a design language element that is, in this day and age, practically universally understood.


yep. on the web it means i have to turn on javascript to view the content. or more often don't bother and close the site. ;)


How can you tell if someone’s vegan at a party? Don’t worry, they’ll tell you.

;)


They usually wont unless you invite them to the dinner. But you can find jokes like you did everywhere.


I use it on buttons that do things. Whether as part of the button or button goes lighter/hover over it with wait cursor (has spinner).


I personally don't mind spinners. They're an explicit indication that something's going on and I should wait. For me, skeletons look more confusing, as if the app is broken: I can see the layout, but everything is empty for some unknown reason and I can't interact with it. Is it loading or just broken? How is the user going to tell? The only issue I have with spinners is when a spinner keeps spinning forever with no feedback because there's an error hidden somewhere in the JS console and the devs forgot to add an error popup. So you are waiting and waiting and nothing happens, and you don't know it's all been just a waste of time.


Skeletons often have a shimmer effect that indicates that the content is loading.

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.


> in a clear way

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.


Skeletons are extremely hard to get right. The system must quickly predict what part of the app is about to load and render the appropriate skeleton. If you make a mistake, or crash, or redirect incorrectly, then you might end up showing a blank screen or something even worse than a spinner. Any screen that doesn't fit an existing layout must have a separate (set) of skeletons created, because showing a mismatching skeleton is very confusing. All this stuff has to account for different devices, as usual. It's almost like maintaining a parallel set of minimalistic designs. It's doable, but only if you have enough resources or if your app is very simple.


From a user perspective, I don't care what you use as long as I can distinguish a frozen state and tell me what task you are stuck on. (IOW, spinners suck).

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.


I don't mind spinners except those ugly 5fps Microsoft "bullets" spinners that I find extremely annoying to watch.


- HTML can be streamed and rendered ad-hoc in the browser.

- 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.


Skeletons are bad news. They usually mean "this app whose UI should already be rendered is heavy, bundled with way too many dependencies, based on an obese framework, built using unnecessarily huge asserts, makes a careless number of API requests and is going to make my fans spin".

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)


Spinners are not just for loading the content, their main place IMHO is in web apps as a way to give user a feedback that their UI action resulted in some action that's currently still running (e.g. an api call in the background that takes some time). For that purpose spinners are probably the best you can do.

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...


I personally believe that loading spinners have permeated to so many apps and websites, and with the rise of using phones more and more (hence slower internet from a tower, rather than from a router) and we end up with a world-wide psychological trick. When I saw the spinners I felt kind of angry because I thought they would never load. I think that if we move on from spinners to skeletons, the same thing will happen - every time someone sees a skeleton, if that is often enough, they might not even bother with the website and might perceive it to be slower.


The point about how people can perceive skeletons differently and how that can affect the emotional impact is interesting, but it's not like the underlying problems have been solved, even the ones posited by the site:

  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.


skeletons are dangerous when you do mutations (POST/PUT) as they suggest the operation has finished, and the user might close his browser window.


Stop using JavaScript-dependent image lazyloading in your webpages (2022)


Yes, spinners are horrible.

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.


I think it's worth noting that fancier ways of showing loading usually take a lot more effort to implement so a loading spinner is a better-than-nothing default.

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.


A much more useful approach, in my opinion, is to simply state that you’re using skeletons instead of loading spinners, because of this and that reason. No need to tell people to stop doing that, do this instead, unless you’re talking about some objectively better way of doing something.


It seems to me that progressive images address this in an elegant way - both showing progress in loading and providing content immediately. They are surely a better option than a spinner, yet they seem far less common on the web now.


> When you looked at the Loading Spinner, did you know how much time remains to complete?

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.


I like to make fat clients with service workers and depend on the server a minimal amount. Helps keep server speeds fast and utilizes all that local processor capacity so the user doesn't have to wait for network latency.

For things that require actually waiting, prefer progress bar first and basic spinner when it's not practical.


As an aside when working on a ship FEM modelling software for hogging and sagging I put together a little animation of a ship going through a rough sea, so which Windows called when it was waiting.

That and working out why a plugin was failing and stating that "There's no init in it, innit". Skill. Savour these moments.


If your page is loading, there needs to be good feedback if it not yet interactive.

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.


They're like thongs. Unsightly on most of us, but we'd rather not talk about what they're covering up.


I personally don't like skeletons prefer just a spinner




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: