We recently made a single page website that used a lot of large images (http://www.astutecertification.com.au) - we knew we'd have to lazy load this thing like nobody's business or it'd take forever to load. But we wanted to use fancy lazy loading that showed blurred versions of the images at first which then faded to the full high-res versions when they were loaded. 

I found this guide to using SVGs to create this effect - it was pretty sophisticated and seemed cool to me at first. But I ran into some problems, the most important of which was a bug in IE which prevented the SVGs from rendering properly on screens larger that 1200 pixels wide - pretty huge problem. I decided to ditch the SVG approach and do something simpler - I decided to use a small, pre-blurred JPEG version of the hi-res image rather than use any SVGs. This led to quite a few other changes to the technique covered at CSS Tricks - I also used the jquery.fullPage plugin to help make the full screen sections, although you can certainly do this without the plugin. 

Prepping the Images

You could set up your images however you need to for your project, but I made mine 1920 pixels x 1080 pixels for the hi-res versions and 192 pixels x 108 pixels for the smaller versions. I also blurred the smaller images using Photoshop, I applied a 3px gaussian blur.

The HTML

The HTML for this technique is very simple, I used Twitter Bootstrap so you'll see some bootstrap classes in there. Note that I have the backgroundImage div and inside that I have the sharp div and the original div. The original div has the background defined inline, I did this so it could be easily changed in the CMS on the final site. The sharp div does not have it's background set yet, it will be set using jQuery when the image has finished loading. The path to the hi-res image is included as a data property on the backgroundImage div.

<section class="section" id="fullscreen-1" data-anchor="section-one">
    
    <div class="backgroundImage" data-src="path/to/hi-res-background.jpg">
        <div class="sharp"></div>
        <div class="original" style="background: url(path/to/blurred-background.jpg) no-repeat center center;"></div>
    </div>
        
    <div class="container">
        <div class="col-sm-12">
            <!-- Section content goes in here -->
        </div>
    </div>
</section>

The CSS

The CSS is also pretty simple, mainly it just ensures the backgrounds are always fullscreen - I also applied some styles to darken the images a bit so that the content would always be legible (I didn't just use filter for this because of issues with IE9). I also made sure to position the original div above the sharp div by setting the z-index property on both divs.

/* Position backgroundImage and make fullscreen */
.section .backgroundImage { 
    position:absolute;
    top:0;
    left:0;
    z-index:1;
    height:100%;
    width:100%;
    overflow:hidden; 
}
/* Apply overlay to darken images, works on IE9 */
.section .backgroundImage:before {
    position: absolute; 
    z-index: 3;
    display: block; 
    content: "";
    top: 0; right: 0; bottom: 0; left: 0;  
    background: hsla(0,0%,0%,0.6);
}
/* Position the original and sharp divs, make fullscreen, set background-size to cover */
.section .backgroundImage div {
    position:absolute;
    height:100%;
    width:100%;
    top:0;
    left:0;
    background-size:cover!important;
}
/* Make original div sit on top of sharp div */
.section .backgroundImage div.original {
    z-index:2!important;
}
/* Make sharp div sit under original div */
.section .backgroundImage div.sharp {
    z-index:1!important;
}

The jQuery

For the jQuery I wrote a quick function, then I needed to call the function and pass through the path to the hi-res background, the sharp div, the original div and the parent section. I'd say you could just get away with the path to the hi-res version and the original div, but I was doing a few other things in my code so I passed through some additional info.

This function firstly adds a new image element, sets the hi-res image as it's source and attaches an onLoad event handler. When the image has completed loading it is set as the background of the sharp div, the original div is then faded out and removed from the DOM (thus revealing the hi-res image sitting underneath it). Additionally, I add a class to the parent section to indicate it is fully loaded, finally the added image element is removed from the DOM.

// Function to swap background images
function swapBg(imageSrc, sharpDiv, originalDiv, section)
{
  $('<img/>').attr('src', imageSrc).load(function() 
  {
    sharpDiv.css('background', 'url('+imageSrc+') no-repeat center center');
    
    originalDiv.fadeOut(500, function()
    {
      $(this).remove();
    });
    
    section.addClass('fullyLoadedMan');
    
    $(this).remove();
  });
}

Now, this is a point where the jquery.fullPage plugin came in handy, it allowed me to fire code when a section had been loaded, it also allowed me to use $(this) to refer to the currently loaded section. I added a slightly more complicated version of the following code to the 'afterLoad' method of the plugin. I setup all my variables and then, if the section included the hi-res background image reference in the data property, I called the function I wrote earlier:

var loadedSection = $(this);
var bigSrcBg = loadedSection.find('.backgroundImage').data('src');
var bgImage = loadedSection.find('div.original');
var bgSharp = loadedSection.find('div.sharp');
// If section includes the relevant data property, call the function
if(bigSrcBg)
{
    swapBg(bigSrcBg, bgSharp, bgImage, loadedSection);
}
           

In the actual project the code was a little more complicated so it could also handle the staff images and project profile images, but it's not difficult to add additional functionality specific to your project to the basic technique covered here.

Wrap Up

This technique allows you to include fancy, blur up style lazy loaded background images in your projects. All the code works down to at least IE9, it may work in IE8 (I didn't test in IE8 though who knows). Another great advantage of this technique is it's very easy to incorporate into a CMS, I used Perch CMS to power this site and it took very little time to get the back-end setup to handle this technique and make it easy for the end-user to change the images in the future without breaking the effect.

Got any questions? Leave em below!

Questions and comments...


Some other recent blog posts...


A great website experience is like a great convenience store

Making life easier for your website visitors gives them a great experience - you can learn a lot from a trip to your local convenience store.


Return to blog index