Your users have latency. As a developer, you should too.

I am going to introduce you to an unpopular opinion right now. Bear with me, this will help you craft experiences with better UX. So promise to read on, despite your instincts might tell you otherwise

Your users have latency. As a developer, you should too.

There are a gazillion ways to optimize the speed of your website. Many of which are hard to implement and will only reduce the loading time by an unremarkable amount.

I am going to introduce you to an unpopular opinion right now. Bear with me, this will help you craft experiences with better UX. So promise to read on, despite your instincts might tell you otherwise 😁

Disclaimer: Only for web apps, not for content/SEO relevant websites:

The UX difference between loading for 1 second vs loading for 0.5 seconds is not as big as the difference between loading for 1 second vs loading for 1 seconds but showing a loading indicator.

Not to say you can't have both (fast loading AND good UX), but more often than not - Yes, I am especially looking at you, indiehacker / solo-founder - I see missing loading indicators, empty content that looks like the app is loading or other bad UX which could be fixed way easier than your asynchronous + deferred JavaScript loading that'll get you 31ms faster first contentful paint.

Got it, use loading-spinners. Anything else?

I am currently working on a web app (Subscribee.net) and I implemented a spinner component to use it as a loading indicator at different places. This way, it's very easy for me and almost no work at all to add a spinner everywhere it's needed.

After some time, I wanted to check something in production, I was messing with some environment variables, and then it hit me: When editing a post, there was no loading indicator while loading the post content and images.

I added the spinner into the respective component but after this incident, I wasn't sure if I may have overlooked something at other places too.

Your users have latency when using your app

When you develop a web app, most of the time you'll run the backend, frontend and database on your local machine. This means that network requests go from your PC/Laptop to itself. No router latency, no (remarkable) latency due to speed of light limit, no load balancing latency, no wireless latency, [...]

Your users will have to query your frontend for HTML, CSS and JavaScript. The JavaScript on the page makes a request to your backend (which in turn fetches data from a database) with which's answer content can be finally displayed. It's impossible to reduce the latency for this chain of actions to the same level as you have on your local setup.

So what's the solution?

Delay each backend response artificially

Delaying each backend response in non-production environments by 250ms in NodeJS is as easy as adding this middleware:

if (!process.env.PRODUCTION) {
  app.use("/", (req, res, next) => {
    setTimeout(next, 250);
  });
}

These 5 lines of code will make sure that you see your web app as a user and not only as a developer. Probably, there are similar methods to delay responses by x ms in non-prod environments for your framework and language.

Like I said, it may seem counterintuitive (to add intentional delay) but you won't ever forget a loading indicator again. I have this snippet in Subscribee's backend, and it works wonders.

Now that you'll easily spot bad UX while the page is loading, you can enhance it where needed. Keep an eye out especially for

  • text that hasn't loaded yet
  • input values that are prefilled but haven't loaded yet (like in my edit-post case)
  • buttons that have been clicked (don't forget to disable them)

Enhancing the Loading UX Even Further

As a bonus, Michal Malewicz, UI Design lecturer and author of "Designing User Interfaces" explained how to improve loading experience even more.

If you remember the first few iPhones, they were pretty slow. Loading an app would often take over twenty seconds, so Apple came up with a solution that would trick the users to think the app is loading faster.

I'm talking of course about Skeleton Screens, a term coined by Luke Wroblewski in 2013. What it means is that they were using a loading screen, that had parts of the layout already rendered on it. If the first app screen was a list, the resulting screen would show an empty list, but with all the boxes and UI elements marked in place.

This led to a perceived lower waiting time by the users, even when the actual time was the same as with an app without a skeleton screen.

This concept was later refined by the use of subtle animation - mostly fading in and out a little, that made the users think that something is happening.

Spinner happens in place, but is not connected to anything. Skeleton backgrounds appear to be there and all you're waiting for is their content - so it appears like half of the screen already has loaded and all we're waiting for is the data.

Summary - TLDR

Main Points of this article summarized:

  1. Work on what makes a bigger impact. Only optimize loading speed until the optimizations get smaller than potential benefits you could achieve with UX optimization. Devs get lost in optimizations way too often.
  2. Use loading spinners, so users know when they can expect more to happen and when the site has finished loading.
  3. Add artificial latency to your local development setup, so you can experience your app like your users would.
  4. If you want an even more optimized UX, go for skeleton screens. Here's more info on skeleton screens.