Simple blur up background image loading with Umbraco and ImageProcessor.Web
Tags: umbraco, tutorial, webdev
Published: 2020-09-16 12:35:44

I'm currently in the process of speed optimizing a website and thought I would share a simple technique that made a big impact.

We as devs create the Umbraco site and of course take care of making sure header/hero images are of a good size (adding the image cropper and ImageProcessor resizing in the mix). But if you're not careful you'll end up with sites where folks are serving several MB of header images... and that makes the initial load of the site painfully slow.

I often use [lazyload](https://github.com/verlok/vanilla-lazyload) to take care of stuff that is below-the-fold... but header and hero images are the first thing you see so that isn't an option.

So here is how I handled it: Blurring up, this means first you serve a lightweight t version of the image and then when the page has loaded we can take care of replacing that with the full blown one.

```
<div class="hero" 
      data-src="@Model.Content.Image.Url" 
      style="background-image: url('@Model.Content.Image.Url?quality=5')">
</div>
```

In this snippet I'm using a low quality v of the image using [ImageProcessor.Web Quality method](https://imageprocessor.org/imageprocessor-web/imageprocessingmodule/quality/) and in the data-src attribute the path to the full blown image is outputted.

Then with some simple js the replace will happen once the page is fully loaded.
```
<script>
    var a = document.querySelector('.hero');
    window.addEventListener("load", function () {
        if (!a) return !1;
        var b = a.getAttribute("data-src"),
        img = new Image;
        img.src = b;
        img.onload = function () {
            a.style.backgroundImage = 'url(' + b + ')';
        };
    });
</script>
```

So now a really light weight image shows up first almost instantly and fetching the full blown version doesn't slow down the initial loading/render... 

Next step is to also take viewport into consideration... 

So adding some inline styling (also limiting the width of the image depending on the viewport)

```
<style>
    .blur-image
    {
        background-image: url(@Model.Content.Image.Url?width=768&quality=5);
       
    }

    @@media (min-width: 768px)
    {
        .blur-image
        {
            background-image: url(@Model.Content.Image.Url?width=1024&quality=5);
                
        }
    }

    @@media (min-width: 1200px)
    {
        .blur-image
        {
            background-image: url(@Model.Content.Image.Url?width=1920&quality=5);
                
        }
    }
</style>
```

And update the js to make sure the correct full image (with width limit will get loaded)

```
<script>
    function setCorrectHeaderBackgroundImage() {

        var w = window,
        d = document,
        e = d.documentElement,
        g = d.getElementsByTagName('body')[0],
        x = w.innerWidth || e.clientWidth || g.clientWidth,
        wi = 768;
           
        if (x > 1200)
            wi = 1920;
        else if (x > 768)
            wi = 1024;

        var a = document.querySelector('.blur-image');

        if (!a) return !1;
        var b = a.getAttribute("data-src"),
            img = new Image;
        img.src = b;
        img.onload = function () {
            a.style.backgroundImage = 'url(' + b + '?width='+wi+')';
        };
    }   

    window.addEventListener("load", setCorrectHeaderBackgroundImage);
    window.addEventListener('resize', setCorrectHeaderBackgroundImage);
            
</script>
```