
Optimising Image Loading Performance and LCP in Silverstripe
- Publication
- Author
- Florian Thoma
- Categories
- Reading time
- 3 minutes
Images are an integral part of the internet. According to the HTTP Archive's page weight report, images make up 26% of the average website's download weight for desktop and 20% for mobile. Because images are so important, it is imperative that we take every step to improve the performance of serving and loading them.
Silverstripe CMS is very flexible and lets you implement almost anything. However, there are a few things that need to be taken care of to achieve optimal image performance on your website. Serving images on the web has many facets: from different image formats to responsive sizing, from lazy loading to LCP images. Let's examine these topics with reference to Silverstripe.
Leverage Modern Image Formats
In recent years, WebP and AVIF have emerged as new image formats that can halve the size of images compared to the old JPG and PNG formats. While WebP has been around for several years, AVIF was only supported in Edge in 2024 and Safari in 2023. According to the 2024 Web Almanac, only 12% of images are WebP and only 1% are AVIF.
While JPG and PNG still have a place as fallback formats, a website should always serve WebP and AVIF where possible. This has become a lot easier with the native image conversion functionality available in Silverstripe 5.3. We override Silverstripe's DBFile_Image.ss
template to serve every image as WebP and AVIF, with a fallback to the original image:
<picture>
<source type="image/avif" srcset="$Convert('avif').Quality(60).URL">
<source type="image/webp" srcset="$Convert('webp').Quality(80).URL">
<img $AttributesHTML>
</picture>
For each format, you can set a quality to be used for the converted image. The original file needs to be JPG or PNG for this to work. You need to ensure that website authors don't upload WebP or AVIF images into the CMS. This can be done in your _config.php
file by removing WebP and AVIF from the allowed upload MIME types:
HTTP::config()->set(
'MimeTypes',
array_diff_key(
HTTP::config()->get('MimeTypes'),
[
'webp' => 'image/webp',
'avif' => 'image/avif',
]
)
);
Responsive Images
To serve responsive images, we use the heyday/silverstripe-responsive-images module. This module allows you to define sets of images that are then served through a picture element with different sources for different viewports. Of course, this can also be combined with the technique described above for modern image formats.
Lazy Loading of Images
Content images, or images "below the fold," should be lazy loaded, meaning they only get loaded once the user scrolls to them. Native lazy loading of images added via the WYSIWYG editor has been available in Silverstripe since 2021, taking care of most content images on a website. For images added to the site in templates, e.g., through $Image.ScaleWidth(150)
, make sure you add loading="lazy"
to the tags.
LCP Images
Largest Contentful Paint (LCP) is a metric measuring when the largest element on the page is painted by the browser during page load. That element can be a text block or, most often, an image. LCP images should never be lazy loaded. Unfortunately, 16% of websites still use that performance anti-pattern, according to the Web Almanac. On the contrary, you want to make your LCP as fast as possible.
Harry Roberts has published "The Ultimate Low-Quality Image Placeholder Technique" for loading an initial low-quality version of an image for LCP as a background image, replacing it with the high-quality version later. In the Silverstripe module innoweb/silverstripe-image-placeholders, I have implemented the LCPLQIP()
method to calculate the low-quality LCP image.
We need to load that LCPQIP image as a background image and then replace it with the normally loaded image source:
<style>
.lcp-image {
background-color: #eee;
background-repeat: no-repeat;
background-size: cover;
background-image: url($Image.LCPLQIP.URL);
}
</style>
<img src="$Image.URL.ATT"
class="lcp-image"
alt="$Image.AltText.ATT"
width="$Image.Width"
height="$Image.Height">
To ensure the LCP background image gets loaded with the highest priority, add a preload tag to the HTML head:
<link rel="preload" as="image" href="$Image.LCPLQIP.URL.ATT" fetchpriority="high">
This ensures that the low-quality placeholder is loaded first, used as a background, and then replaced with the actual image once it's loaded through normal means.
Combine Everything for Best Results
To achieve the best results, it’s essential to combine these techniques effectively. For instance, when optimizing LCP images, ensure that the image is in a modern, efficient format and properly sized for the current viewport. Then use the Low-Quality Image Placeholder Technique to load the LCP image.
This process may require some fine-tuning to align all the elements seamlessly. However, once everything is configured correctly, you’ll enjoy the best possible image loading performance.
Feel free to contact us if you’d like assistance optimising the images on your Silverstripe site!