Skip to content Accessibility

Non-blocking UIs with interface previews

Improving the perceived speed of interfaces using skeleton loading screens plus other front-end/UX performance gains.



This article made it to the front page of Hacker News and has been translated into Japanese.

What are they #

I like to think of non-blocking interfaces as skating on ice and blocking ones as trudging through mud. A non-blocking interface should feel fast, responsive and continuous, regardless of network speed. Any action such as loading a new page or clicking a button should have an immediate reaction, and should never be left in limbo.

One technique I've dubbed as "interface previews" (aka skeleton screens), is very effective when designing for non-blocking interfaces. Page layout and placeholder elements are rendered immediately whilst waiting for the data to populate them. These placeholder elements in a way act as proxies, though it probably better illustrated with a picture.

Screenshot of skeleton elements rendered whilst Facebook fetches remote data.

This screenshot was taken when Facebook's website was first loaded. At this point we are still waiting for data to be sent down, but we can see the page layout and some key elements such as where images and text will be. Will be is the key part here as the interface is showing us what it is going to look like at some point in the future.

Why they are good #

Interface previews / skeleton screens yield a fantastic user experience. Users can use the time normally spent looking at a white screen or an AJAX spinner getting familiar with the layout of your app.

More importantly users can begin using parts of your site that aren't dependent on the server. For example in EffortLESS the links to recent shares are stored in local storage, so can be shown to the user straight away. A user can click on one of the links instantly; which means they aren't forced to wait for the whole page to load before navigating away from it.

Screenshot of skeleton loading elements and links that can be shown immediately.

Non-blocking interfaces also increase perceived speed which is how fast users think your app is, rather than how quick it is on paper. Users don't care about performance stats in terminal, they care about what they see in front of them; which is the interface you've spent ages perfecting.

The degree to which you use them #

Users see interface previews for a split second, and in an ideal world won't see them at all. The amount of time you spend on them depends on time constraints, use cases and the nature of the project. I've split the degrees in which interface previews can be implemented into 3 levels: bare bones, aspiring and perfectionist.

Bare bones #

The least amount of work with the biggest impact is showing page layout and elements that are decoupled from the server. Despite being called bare bones this is very effective as it removes the white screen / ajax spinner approach, and is more than sufficient for most cases.

Aspiring #

A finer grained approach is to show placeholder elements and text. In EffortLESS the boxes for each colour, the share button and the help text all have placeholder states which can be seen below.

Comparison of an element before and after its remote data is available.
Screenshot of a non-interactive button shown when data is loading and an interactive button for when data arrives.

Perfectionist #

For those that never believe the work is done there is the perfectionist approach. These types of details are pretty specific and will vary between applications.

In EffortLESS I added placeholder text elements for the share button and the help text for recent shares / clips. Although not dependant on the server the text doesn’t make sense until the data has arrived. You can't share anything if the data to share is still on its way, and likewise you can't add a colour to clipboard if the colour isn't there.

Screenshot of recent shares and items on clipboard before and after remote data has loaded.

Implementation and general advice #

The nature of interface previews means they have a few prerequisites. Client side rendering with frameworks such as Backbone, Angular or React is a must. They would be very hard to achieve using the conventional server driven approach. Your client-side mv..whatever also needs to have asynchronous communication with the server. Promises come to the rescue here as they can update views once resolved, (I’m a big fan of the library q). Update: I've built a library called Preact that adds interface previews to React components.

Aside from architecture and tools I found some handy techniques for tackling interface previews whilst building EffortLESS.

Firstly separate placeholder elements from the real ones they're covering for. By separate I mean have 2 templates; one for the placeholder element, and another for the real element (that's shown when its data has arrived). Initially, I used one element and toggled its class depending on if it was in its preview state or not. Although this approach works there are a few drawbacks:

  • The structure of the element is generally different for its two states. So you effectively have one template that contains two sets of markup that are conditionally shown / hidden.
  • As a result view logic becomes a little convoluted.
  • Any markup saved using one element is lost as extra markup is needed to disable any interactions users can have with the placeholder element. A user shouldn't be able to click or focus a placeholder button or form input, and hover states need to be removed as they're misleading.

Another problem I came across with EffortLESS was knowing how many placeholder colours should be shown. It would look rubbish if there were ten placeholders and only six colours arrived. In actual fact it would appear broken, as if four were lost on the way. Placeholder colours are only needed for shared urls, so appending the number of colours to the url when it's created did the trick. When that url is visited we can work out how many placeholder colours to render on the client (using substring), way before any data has arrived.

Something which has become invaluable in my toolbox is Network Link Conditioner. It allows you to test your designs at different internet speeds, and mocks slow response times way better than throwing a few timeouts into your code. This is a great guide for getting started with it. Seeing how your app performs across slow networks is very useful for not only testing how successful your interface previews are, but also gives you an insight into the degree to which they should be used. You can now use throttling in Google Chrome's console to similar effect.

A great companion to Network Link conditioner are the benchmarks established by Jakob Nielsen. In the book usability engineering book he identifies three time limits that show us just how important the need for speed is:

  1. 0.1 seconds. Operations that are completed in 100ms or fewer will feel instantaneous to the user. This is the gold standard that you should aim for when optimizing your websites.
  2. 1 second. Operations that take 1 second to finish are generally OK, but the user will feel the pause. If all of your operations take 1 second to complete, your website may feel a little sluggish.
  3. 10 seconds. If an operation takes 10 seconds or more to complete, you’ll struggle to maintain the user’s attention. They may switch over to a new tab, or give up on your website completely. Of course this depends on what operation is being completed. For example, users are more likely to stick around if they’ve just submitted their card details in the checkout than if they’re waiting to load a product page.

I've only just started playing with interface previews but so far can't find an excuse not to use them! As of 2016, I have seen skeleton screens in: Facebook, Medium, Pinterest, Netflix and Drupal, and of course the ever popular, EffortLESS.

If you liked this post and want more I suggest checking out:

P.S. Shout out to Tobias Ahlin for his awesome CSS spinners I used on EffortLESS.

About the author

I'm Callum, a Front-end Engineer at Nutmeg. Previously I wrote code for KAYAK, American Express, and Dell. Out of hours I publish blog posts (like this one) and tweet cherry-picks.

Feel free to follow or message me at @_callumhart on Twitter.