Background images are evil
Learn why to avoid background images on your website, how to quickly find background images and how to fix this issue
Background images are evil
Those of you that ik now me or have heard me speak might have heard me talk about background images. Those of you who have not: I really really do not like background images. In this article I will quickly explain why don't like background images, how to quickly find pages with background images and how to fix them!
Why background images are bad for the Core Web Vitals
When loading a web-page every element has it's time and it's place. With some modern techniques like deferring, preloading, async loading, scheduling, defining the fetchpriority etc etc we can get all critical resources pretty much under control. Except for background images!
Consider this real-world example:
On a daily basis, mostly in WordPress sites I see this pattern. All the normal images are lazy loaded and some images (in this case the social icons in the footer) are background images Can you guess what happens?
<html> <head> <style> footer { /* a margin of 100 vh wil make the footer off-screen !*/ margin-top: 100vh; >.social { >.facebook {background-image: url('img/facebook.jpg');} >.instagram {background-image: url('img/instagram.jpg');} >.linkedin {background-image: url('img/linkedin.jpg');} >.email {background-image: url('img/email.jpg');} } } </style> </head> <body> <!-- yes this image is lazy loaded, because tiny mistakes happen! --> <img loading="lazy" src="img/hero.jpg"></img> <footer> <div class="social"> <span class="facebook"></span>
<span class="instagram"></span>
<span class="linkedin"></span>
<span class="email"></divspan
</div> </footer> </body> </html>
You might have guessed it: the offscreen background images are queued for download before the far more important 'hero.jpg' image which will usually become the largest contentful paint element on the page.
But that is not all!
As I said background image are evil! That is because, aside from the weird priority that they sometimes get background images lack the cool features that normal images get!
- No lazy loading: there is no loading attribute for background images
- No async decoding: there is no decoding attribute for background images
- No fetchpriority: there is no fetchpriority attribute for background images
- Responsive image sources: The image-set() attribute for background images does not have the same power of features that you get with good responsive design.
- No width and height attribute. Not being able to set the simple width and height attribute will make you use workarounds that require code (more code is always slower then less code with the same complexity!)
- No alt text: while this does n
Quickly find all background images on a page
let bgimg = performance.getEntriesByType('resource') .filter(rs => rs.initiatorType == 'css') .map(rs => { return { name: rs.name, initiator: rs.initiatorType } }) || []; (bgimg.length > 0)? console.table(bgimg): console.log('No background images on this page!');
This will show you a cleanly formatted table with all the background images names and the initiators
How to avoid background images
Background images are easily avoidable. How to do this depends on the image itself. There are roughly 2 methods.
In case of 'normal images'
You would not believe it if I told you but the majority of the cases where I find background images the background part of the image does not even have a purpose. The images just 'need to be somewhere on the page' and the background-image:url()
is misused for this purpose.
If this is the case just add a normal image tag and remove the background image from the stylesheet.
In case of cover images:
Cover images ar eimages that completely cover a parent container. Using background images as cover images sort of makes sense because a long time a gho this used to be the only way to get cover images and I guess people just stick to what they know. Fortunately there are better options available to us. So let's fix it!
In case of cover images just remove the style background-image: url(hero.jpg); background-size: cover;
a and place a normal image in that same container and edit the CSS to look like this:
<style> .img-container { position: relative; > img { width: 100%; height: 100%; object-fit: cover; position: absolute; z-index: 1; } } <style> <div class="img-container"> <img height="500" width="300" decoding="async" loading="lazy" src="hero.jpg" srcset="hero-320w.jpg, hero-480w.jpg 1.5x" alt="alt text" fetchpriority="low" > </div>
Join the Core Web Vitals Revolution
CoreDash smart & real-time Core Web Vitals tracking: faster websites & happier visitors.
- Easy set up
- No credit card required
- No strings attached