Two seconds of loading time is all it takes for 40% of your users to lose patience and leave your site or app. Here are three questions you should be asking yourself that will help prevent overload and keep your website or app snappy.
Once you’ve made your server do what it’s supposed to as fast as it can, it would be a shame to ruin your effort with a page that displays too slowly to keep your users hooked.
Beyond the initial HTML document returned by the server, browsers need to fetch a few other resources to render a page in all its glory:
- CSS file(s) to layout and style the content in the HTML file
- images that form part of the content, or used as backgrounds
- fonts to give the text a bit of personality
- JavaScript to add client-side features to the page
- other media like videos, 3D models and so on
This means bringing in KBs (if not MB) of data, and this can have a massive impact on your loading speed. At the time of writing, 50% of pages on the web are larger than 1.5MB for the user, taking multiple round trips to the server and then having the browser process them. Each step adds to the delay in users getting what they wanted from your website (not to mention the extra cost for them).
Looking for expert guidance or developers to work on your project? We love working on existing codebases – let’s chat.
With that in mind, here are three questions you should be asking yourself each and every time you add content or a feature to your site.
1. Is the feature worth the KBs?
Each feature brings with it a lot of resources necessary for it to run. Some will be just a couple of extra HTML tags or a bit of CSS, while others could bring in huge video files or heaps of JavaScript (I’m looking at you third party trackers and ads).
‘Find the lightest acceptable solution in each situation, rather than reaching for a heavy option out of habit.’
Assuming those features are there for a reason (it’s healthy to question if they’re really necessary), the way you implement the feature will often provide an opportunity for cuts.
You could ask yourself:
- Is that fancy webfont absolutely necessary, or will the design remain purposeful and engaging with system fonts?
- Is 100% of that JavaScript library being used, or is the feature only using a couple of lines that the devs could extract?
- Is that library necessary at all? JavaScript is extra costly, due to it having to be loaded in memory and executed before anything happens. Maybe HTML, CSS and good old HTTP navigation would allow the user to meet their goal as well?
Again, this doesn’t mean you need to make cuts at every chance you get. It’s about finding the lightest acceptable solution in each situation, rather than reaching for a heavy option out of habit or because it had the most stars on Github. Each KB you don’t send to the browser is a KB that won’t slow down your site.
2. Is all of it necessary?
Now that you’ve picked the lightest solution, the next step is to see if there are ways to make it even lighter. At least before it reaches the browser.
‘An awareness of what your users are trying to accomplish will help you make good decisions about what gets prioritised.’
For each type of resource a page might load, there’s something you can do (and most of the time automate) to make it leaner.
- CSS: Humans need all that white space in the code but computers don’t, so minification is a must. Beyond that, there’s also a case for looking at how much unnecessary CSS you’re loading. When using libraries (animate.css, spinkit, loaders.css…) or frameworks (Bootstrap, Foundation, Bulma…) to speed up development, chances are you’re not using 100% of the CSS they provide. Sending all of it to the user is a waste in that case. CSS preprocessors (or copy/pasting) can help you pick just what you need and reduce the bloat.
- Images: Sure that 4K image looks great with all its detail. But a mobile device won’t need all those pixels to display a crisp image. The first step to avoid bloat in your images is loading sizes that are adapted to the screen that’ll display them. This not only saves on the download time, but also reduces the computing time spent to resize them. For <image> tags, the `srcset` and `sizes` attribute will let you adapt them to the viewport. And media queries will help you do the same for background images. From there you can save more by picking the lightest format and running an optimizer on them.
- Fonts: Platforms like Google Fonts or Typekit offer hundreds of fonts, tempting you to use many in your design. Even if they’re in the WOFF2 format (the most optimised at the time of the writing), that’s tens of KB to download each font. Unless you’re able to use variable fonts, each variant (bold, italic…) will be a separate file, so limit the number of families and variants you use in the design.
- JavaScript: As for CSS, authored code contains many characters that are unnecessary for a browser to do its job (spaces, long variable names…) and minification will save loads there too. Likewise, making sure your final JS file(s) only contain the parts of the libraries you’re actively using will reduce the size further. If you’re writing ES2015 and bundling it with Webpack, tree shaking will take care of that for libraries that have been written with it in mind. This is something you should look out for when choosing what to use.
3. Is it needed right now?
Now, the actual size of each file obviously impacts the load time of your page. But it’s only part of what actually matters for your users – how soon can I do what I came here to do?
The sooner your users can reach their goal, the better. Maybe they could progress to the next step of that form without the JavaScript being loaded? Or maybe it’s more important that they read the copy than see a background video first?
Having an awareness of what your users are trying to accomplish and what their priorities are will help you make good decisions about what content gets prioritised.
‘There’s no universal set of rules for all sites – different sites will benefit from a focus on different areas.’
Once you’ve brought every resource down its lightest weight, there’s another lever to play with to get your users a faster experience – how the resources are loaded by the browser. Not all resources are necessary from the start – at least in their entire form – so that’s something you can play with.
Here’s what can be done for each:
- CSS: The first thing is to make sure most of it is loaded in the `<head>` tag, in the minimum number of files. CSS will block render so anything encountered in the body will slow things down. But there’s also room to optimise by extracting the CSS for what will be visible first (the critical CSS) into the HTML so the page renders nicely while the rest of the file downloads asynchronously.
- Images: Images further down a page shouldn’t load until the user actually scrolls them into view. Lazy loading them can help reduce the number of requests sent during the initial load. Past the bandwidth saving, this allows more important requests to reach your server first as browsers limit the number of concurrent requests to a single server.
- Fonts: Fonts take some time to load, but that doesn’t mean users have to wait for them to read the text. The important thing here is using a loading strategy that will avoid the text not displaying while it loads.
- JavaScript: Without any further indication, every time a browser sees a `<script>` tag, it’ll try to execute it (and download it if it’s not inline) slowing render. This is one of the reasons to place them before the closing `</body>` tag. You can also use the `async` and `defer` attributes to tell the browser to load the script asynchronously, keeping the rendering smooth. Asynchronicity is especially important when loading third party scripts. You can’t control how big they’ll be or what they’ll run when they load, so best not open the door to them by blocking things right from the start. As for the images, there’s also a case for asking if all of them are needed from the start or for all the pages. Only loading a heavy JS widget on the pages where it’s actually used, or at the time it’s actually displayed, can help speed up the rest of the site.
There’s no universal set of rules for all sites – different apps will benefit from a focus on different areas. For a single page app, you’ll gain the most by looking at the JavaScript, while a photographer’s portfolio requires a deeper look at the images.
There are other factors beyond these three questions at play too – with some levers to play with at network level (prefetching hints, caching…) or using design ‘tricks’ to make loading feel faster for the user.
In the end, you’re never going to be able to tune everything perfectly. But hopefully the answers to these three questions will point you toward ways you can improve your existing codebase little by little and prevent performance decay for new ones.
If you have an app that you feel is too slow or could be faster, drop us an email to talk through your options.
You could also put your questions to our panel of experts at Design/Build/Market: Performance Matters, on the 23rd October at The Engine Shed, Bristol.
Join us for an evening of talks from professionals in the fields of design, development and marketing, and explore performance optimisation techniques that can have a big impact on your business.