skip to main content

Jay Freestone

The performance benefits of progressive enhancement

Snippet of progressive enhancement code

Progressive enhancement focuses on providing a core ‘device-agnostic’ experience for all users. By starting with a solid foundation that works everywhere – HTML – we ensure our applications are usable for as wide an audience as possible. This encourages us to pare down our applications to their essential features, be it reading the news or sending and receiving messages. Once we’re confident this core experience is functional for everyone, we can start to layer on styling and interaction to provide a better experience for devices which support it.

A comparison of a website before and after CSS and JavaScript.
Simple HTML, before and after CSS and JavaScript.

Although progressive enhancement is a popular technique for content-driven sites, it’s often ignored on modern web apps since it de-prioritises more ‘dynamic’ features that likely wouldn’t work on older devices. However, while the main advantages of progressive enhancement are traditionally seen as reliability and compatibility, there are also many performance benefits that come from adopting a PE-friendly mindset that make it more than worth considering for your next application.

Faster time-to-interactive

Many modern apps utilise client-side frameworks (such as Angular and React) to provide their ‘core’ experience. These often require downloading the full application to the device before becoming usable, resulting in a long delay for users on slower connections.

A progressive enhancement timeline taken from Chrome console
A large JavaScript bundle delaying time-to-interactive.

While client-side rendering can be great for repeat visitors or dynamic features, serving simple HTML is still the fastest way to get your application in the hands of your users. There’s no waiting for large files to download and execute — you get instantly-usable HTML without any dependencies. By starting with simple HTML/CSS, you let your users interact with your app as soon as possible.

Non-blocking font loading

Web fonts have become extremely popular in recent years, but the best way of loading them is still a contentious issue. Serving them to everyone immediately can lead to the infamous ‘flash of invisible text’ while the browser downloads the font, which on some browsers (such as iOS Safari) leads to invisible content for as long as the font takes to download.

An image of our website header with hidden text
It’s there, you just can’t see it.

Instead, we can use an already available ‘system’ font (such as Arial) and then only swap it out when we’re sure our custom font is ready and supported. This means the content will always be visible, regardless of the device or network capabilities. This may be distracting on the first visit, as the font will visibly change after a few seconds, but is preferable to hiding content.

An image of our website header with text

This is the basic principle of progressive enhancement —  starting with a reliable and fast experience, then ‘layering’ on enhancements when we can.

Conditional loading

Some of the most impressive features on the web mimic native apps, such as real-time chat and ‘WYSIWYG’ editors. Unfortunately, these can often be very large and complex files, usually JavaScript, that result in slower sites and larger downloads.

Taking a PE-friendly approach means ensuring the core functions behind these actions (e.g. typing content, sending a form) don’t rely on external files or JavaScript. Then, in the background, we can ‘progressively’ load the enhanced versions of these features and swap them out when ready. Better still, we can load these assets only when relevant and not (for instance) if there is no WYSIWYG editor on the page.

A gif showing the progressive enhancement of conditional loading on a text box

A simple text area, becoming a WYSIWYG editor when clicked

This means that users don’t need to wait for core functionality within your application. If they’re on a slow device or network connection they can still use a simple version of a feature without waiting.

Being selective

We can take our conditional loading of ‘enhanced’ features one step further by being even more selective about who receives them.

Many older browsers have poor support for modern features, often necessitating the addition of large helper libraries (known as ‘polyfills’) to fill in the gaps. This usually means serving visitors larger files than they need, just to cater to the lowest common denominator.

Instead, we can employ a technique the BBC has referred to as ‘cutting the mustard’. We can run a simple test when our website loads that will check for the existence of ‘modern’ features and then load the appropriate file based on the result. Modern browsers get the modern code, older browsers get the larger backwards-compatible code, and very old browsers don’t get any of the enhancements.

A code snippet of the BBC's Cut the mustard selective loading code

By checking up front, we can ensure users only download and run appropriate code. Even better, since the basic functionality is usable without the enhancements, users can still interact with the page while this is going on in the background.

One more thing

Of course, there are a bunch of other benefits of a progressively-enhanced application. Your app will be far more error tolerant — if something goes wrong with a fancy new feature, there’s a good chance your users will still be able to complete their task with the ‘basic’ version.

Progressive enhancement also helps save time when it comes to cross-device testing since you can be safe in the knowledge that your app will only layer on features when they’re supported. Practically everyone is guaranteed a functional experience, regardless of browser or device.

Although everyone appreciates better performance and resiliency, progressive enhancement remains a contentious issue. Some developers feel the approach limits their ability to provide dynamic experiences, especially those that mimic native applications. Many modern tools and frameworks, such as React and Angular, are written entirely in JavaScript. While these provide a fast, ‘app-like’ experience, they also won’t (usually) work for customers who have JavaScript disabled, or if there is a problem with parsing the script. Others consider the future of progressive enhancement to be in network resiliency, ensuring that pages work ‘offline’ thanks to new technology such as PWAs based on service workers.

Like all techniques and methodologies, progressive enhancement doesn’t need to be followed dogmatically and is more a guideline than a rule. However, it’s a valuable mindset that can help improve your application for all users, not just those on slower or less capable devices.