Question

I am trying to fade in/out a background image on scroll.

I am using jQuery .addClass()/.removeClass() to trigger the event and CSS3 to change the opacity of the second background.

I would like to stick to CSS3 for the animation but there is a white flash when the animation is triggered on chrome.

FIDDLE

Is there a way to prevent this flash?

HTML :

<div class="second_bg"></div>

CSS :

body, html {
    height:150%;
    margin:0;
}
body {
    background: url("http://lorempixel.com/output/nature-q-g-640-480-9.jpg") repeat scroll 0 0;
}
.second_bg {
    opacity:0;
    height:100%;
    background:#566c75;
    -moz-transition: opacity 0.5s ease-in;
    -webkit- transition: opacity 0.5s ease-in;
    transition: opacity 0.5s ease-in;
}
.fade-blue {
    opacity:1;
}

jQuery :

$(document).ready(function () {
    $(window).scroll(function () {
        if ($(window).scrollTop() > 20) {
            $(".second_bg").addClass("fade-blue");
        } else {
            $(".second_bg").removeClass("fade-blue");
        }
    });
});
Was it helpful?

Solution

The few tricks below can help to prevent flickering — simply apply them to the <body> element:

  • -webkit-backface-visibility: hidden; See demo
  • -webkit-transform: translate3d(0,0,0) See demo

It has worked without an issue for me, but for some reason when I test them out in your Fiddle, the properties seem to give problems when scrolling within an iframe — so you should be cautious when using this fix for production releases, or at least test them first.

p/s: Tested on a local machine, worked for me.

OTHER TIPS

Updated Fiddle To fix this, you can add this in the css (body):

-webkit-backface-visibility: hidden;

JSFiddle

Use this method instead:

<div class="second_bg"></div>

Keep the html the same.

jquery:

$(document).ready(function () {
    $(window).scroll(function () {
        if ($(window).scrollTop() > 20) {
            $(".second_bg").fadeIn();
        } else {
            $(".second_bg").fadeOut();
        }
    });
});

Change this css class to:

.second_bg {
    display:none;
    height:100%;
    background:#566c75;
}

Instead of adding and removing a class, have it always have the background position, just with display:none;.

Then, you can fadeIn and fadeOut to get the effect you want instead.

Adding -webkit-transform: translate3d(0,0,0); to the body, which enables hardware acceleration seems to work.

DEMO

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top