Render blocking issue with dynamic <body> background-image

391 views
Skip to first unread message

Taylor Wood

unread,
Jan 21, 2015, 9:32:24 PM1/21/15
to pagespeed-ins...@googlegroups.com
Hi,

We dynamically add a background-image to our body tag. Using jQuery code like this:

$('body').css('background', 'url(/images/background-image.jpg)');



I do this at the end of the page to make sure it doesn't block the page from loading.  I've also tested having it load after everything else has loaded.

What I'm finding is though, that by having this at the end of the page, it makes all other scripts get marked as render-blocking content.

The example code below shows the typical set up. With the background-image script enabled, all scripts are marked as render-blocking.

<html>
<head>
<script src="/header.js"></script>
</head>
<body>

<script src="/some-other-script.js"></script>

<script src="/footer.js"></script>
<script>$('body').css('background', 'url(/images/background-image.jpg)');</script>
</body>
</html>




When I comment the background-image script out, only the /header.js script is render-blocking - which is correct and what I want.

Is it possible to add a background-image to the body tag after the page has loaded without causing render-blocking issues?

Am I doing something wrong?

I'd also like to add that in terms of the what it looks like when the page loads - the content loads first, and then the background-image loads afterwards - which is why I don't understand how it can be render blocking.

Thanks,
Taylor

Carlos Lizaga Anadon

unread,
Jan 22, 2015, 5:23:52 AM1/22/15
to pagespeed-ins...@googlegroups.com
Why not load it just with CSS? 

Regards.

Rick Steinwand

unread,
Jan 22, 2015, 10:09:27 AM1/22/15
to pagespeed-ins...@googlegroups.com
Have you tried:

$(document).ready(function(){$('body').css('background','url(/images/background-image.jpg)');});

Taylor Wood

unread,
Jan 22, 2015, 6:59:03 PM1/22/15
to pagespeed-ins...@googlegroups.com
The background-image is dynamic, based on other variables that need to be loaded on the page first. This is why I load the background-image last.

iTaylorJay

unread,
Jan 22, 2015, 7:02:07 PM1/22/15
to pagespeed-ins...@googlegroups.com

Hi Rick,

Thanks for your suggestion. I have tried this - but still the scripts in the body are marked as render-blocking.

I will add though, doing it this way makes the page load a lot visibly faster. The content loads first, which is ideal, and then the background-image loads up afterwards. But for some reason, the content scripts are still render-blocking!

Carlos Lizaga Anadon

unread,
Jan 23, 2015, 5:16:07 PM1/23/15
to pagespeed-ins...@googlegroups.com
jQuery should be blocking the render too.
You can still do this this way:

function backgroundChange() {
    $('body').css('background','url(/images/background-image.jpg)');
}

if (window.addEventListener) {
    window.addEventListener("load", backgroundChange, false);
} else if (window.attachEvent) {
    window.attachEvent("onload", backgroundChange);
} else {
    window.onload = backgroundChange;
}

Regards. 

Carlos Lizaga Anadon

unread,
Jan 23, 2015, 5:20:04 PM1/23/15
to pagespeed-ins...@googlegroups.com
And by the way, this is the cool way to do it:

var dfLoadStatus = 0;

var dfLoadFiles = [
    [
        "blabla..." // more libraries jQuery dependant.
    ]
];

function downloadJSAtOnload() {
    if (!dfLoadFiles.length) return;
    var dfGroup = dfLoadFiles.shift();
    dfLoadStatus = 0;
    for (var i = 0; i < dfGroup.length; i++) {
        dfLoadStatus++;
        var element = document.createElement('script');
        element.src = dfGroup[i];
        element.onload = element.onreadystatechange = function () {
            if (!this.readyState || this.readyState === 'complete') {
                dfLoadStatus--;
                if (dfLoadStatus === 0) {
                    //If jQuery is loaded load jQuery depedant scripts
                    if (dfGroup.length === 1) {
                        downloadJSAtOnload();
                    //If all scripts are already loaded,
                    //launch deferred actions
                    } else {
                        performDeferredActions();
                    }
                }
            }
        };
        document.body.appendChild(element);
    }
}

if (window.addEventListener) {
    window.addEventListener("load", downloadJSAtOnload, false);
} else if (window.attachEvent) {
    window.attachEvent("onload", downloadJSAtOnload);
} else {
    window.onload = downloadJSAtOnload;
}

function performDeferredActions(){
    //This will be executed after all jQuery libs are loaded.
    $('body').css('background','url(/images/background-image.jpg)');
}

Regards.

iTaylorJay

unread,
Jan 27, 2015, 8:12:48 PM1/27/15
to pagespeed-ins...@googlegroups.com
Hi Carlos,

Thanks for your suggestion below. I have tried this on the site, but still the body scripts are getting marked as render blocking.

I can see that the background is the last thing to load, after all the content - I really don't understand.

The only success I have had is setting a timeout function and having the background appear after 5 seconds. This seems to make Google happy in terms of render blocking content, but surely that can't be the best way to do it!

Cheers,
Taylor

Rick Steinwand

unread,
Jan 28, 2015, 3:34:00 PM1/28/15
to pagespeed-ins...@googlegroups.com
Can you post a link to the page?
Reply all
Reply to author
Forward
0 new messages