As a cycling enthusiast, the Tour de France has always been a spectacle for me. But this year for the first time I'm delving deeper into the event day by day which made me engage more with the event app, where I noticed opportunities for improving the user experience.
The Tour app is visually appealing and well-designed. However there are some performance issues in the webapp that can be easily fixed.
For example, each stage features a hero section with 3 large high-resolution images, while visually stunning, these images can cause slow loading performance particularly on slower connections or low-end devices, let's take a look at the network tab here.
As we see, the same image size is loaded for all screens, however we can serve smaller images for mobile devices which would improve the LCP
<div class="rider">
<img
src="rider-image1-large.png"
srcset="
rider-image1-small.png 480w,
rider-image1-medium.png 800w,
rider-image1-large.png 1200w
"
sizes="(max-width: 480px) 480px, (max-width: 800px) 800px, 1200px"
alt="Rider Image"
/>
</div>
srcset
provides a list of image sources with their corresponding sizes. The browser will choose the best image based on the device's screen size and resolution.rider-image1-small.png 480w
: This image will be used if the screen width is 480 pixels or less.The same applies for medium and large sizes.
sizes
specifies the width of the image in the layout viewport, which helps the browser decide which image to choose from the srcset
.
(max-width: viewport max width size in pixels) image-size
Here is a full example: https://codepen.io/majidzeno/full/WNqwxNr
But what if the user's connection is slow ? showed we provide the same user experience for every user ?
Ideally, yes. However, in the real-world not all devices have the same capabilities nor connection speed. Therefore we need to plan for worst-case scenarios.
We can use Network Information API, which helps us determine if a user has a poor connection or is in power-saving mode, so we can show lower-resolution images till the connection improves. In some other cases we can even allow users to request higher-resolution images manually.
Here is an example:
<div class="rider">
<img id="rider-image" src="loader.gif" alt="Rider Image" />
</div>
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
// I will assume 3g is low quality connection
const isLowQuality = connection.effectiveType.includes('2g') ||
connection.effectiveType.includes('3g') ||
connection.saveData;
document.getElementById('rider-image').src =
isLowQuality ? 'rider-image-low.jpg' : 'rider-image-large.png';
If the connection type is 2G, 3G, or the device is saving data, we consider it low quality.
This helps us decide which image to load based on the connection speed.
This technique called Adaptive loading, here is a full example https://codepen.io/majidzeno/full/ExBKZvR
In this example check normal loading and try to emulate slow-connection, in normal cases we will load large images
However, if we changed connection to be slow, we will load much smaller images to maintain an acceptable loading speed.
Implementing adaptive loading can signifcantly enhance the loading speed and overall user experience. Shoutout to Addy Osmani for showing the power of adaptive loading.
Last but not least, it's worth noting that the tour web app utilizes the Intersection Observer API. This helping improve performance by loading only the content users need as they scroll through the page. It's particularly useful for lazy-loading images.
These tweaks can make the app smoother for everyone, no matter their device or connection which can make the Tour de France digital experience as exciting as the race itself.
I cross-posted this on Medium too.
Top comments (0)