0HTML5 LogoResponsive lazy backgrounds instead of css background-image

I’ve recently been work­ing on an update/overhaul of both my vari­ous web­sites and the serv­er backend. As part of this pro­cess I’ve been try­ing ot make sure everything is using the latest stand­ards to max­im­ise per­form­ance and com­pat­ab­il­ity. One of the best fea­tures of recent ver­sions of word­press is the nat­ive sup­port for respons­ive images — where the img­set=”” attribut eis used to sup­ply altern­at­ive sizes of images in a group so the browser can use the most appro­pri­ate. In com­bin­a­tion with async load­ing and lazy load­ing this can make pages load far faster whilst still look­ing good to all vis­it­ors. How­ever css has not adop­ted these new­er fea­tures so back­ground images are much trick­i­er to deal with. It can be done though…

It is pos­sible to use media quer­ies in CSS to provide an appro­pri­ately sized image for most vis­it­ors. How­ever here is no equi­val­ent of async or lazy load­ing for CSS so your (prob­ably large) image will hold up page ren­der­ing which can make a huge dif­fer­ence on a slow con­nec­tion. The pagespeed insights tool for one of my sites was see­ing a render time of around 1 second vs 4 seconds just by adding the back­ground image. 4 seconds it too long, but I did­n’t want to lose the back­ground image, so I wondered if it was pos­sible to have a div ele­ment with a nor­mal lazy loaded image in it and to fit that to the page and put it behind every oth­er element.

I did some search­ing and found a CoreWeb­Vi­tals art­icle by Arjen which talked about the exact same issues I was hav­ing. How­ever the code provided there did­n’t do what I needed, it appears to be for a div that is meant to be part of the flow of a page.
After some play­ing around on code­pen and a help­ful sug­ges­tion by luuk­vhoudt on stack­over­flow that google turned up I was even­tu­ally able to get code that worked to make a nor­mal image in html act just like a back­ground image. Like a css back­ground I was able to set all of the desir­able behaviours…

  • Image fills full width of screen
  • Image keeps aspect ratio
  • Image is ver­tic­ally centred (so top and bot­tom are cropped)
  • Image stays in pos­i­tion when scrolling page down
  • Image does­n’t inter­fere with any oth­er ele­ments on the page
  • Even when view­port becomes ‘por­trait’ the image still fills the whole width and height and keeps the cor­rect aspect ratio
  • Thanks to HTML the image loads async and lazy so does­n’t impact performance

The code needed was actu­ally sur­pris­ingly easy. The HTML code goes imme­di­ately inside and at the top of the body tag, and then a little CSS does the rest. Note that you should put the smal­lest image in the src=”” attrib­ute. I’ve also used aria-hidden=“true” to tell screen-read­ers to ignore our image since it’s meant to be a background


<div id="bg-container">
<img src="/path/to/bg768.jpg" aria-hidden="true" alt="background" decoding="async" loading="lazy" srcset="/path/to/bg768.jpg 768w, /path/to/bg1024.jpg 1024w" >
</div>

Next the CSS

#bg-container
{
display: inline-block;
overflow: hidden;
position: fixed;
width: 100%;
height: 100%;
pointer-events: none;
z-index: -1;
top: 0px;
left: 0px;
}
#bg-container img
{
width: 100%;
height: 100%;
object-fit: cover;
}

Leave a Reply