I think what you are seeing is referred to as Jank.
It happens because of the CSS properties you are trying to animate. Both of these 2 CSS properties i.e. left
& background-position
trigger paint & compositing operations. Additionally, left
property triggers layout as well.
Have a read on the subject of High Performance Animations and also take a look at which CSS properties trigger which operation over at CSS Triggers.
As a solution, you might want to animate translateX
instead of left
property. The result will be a little better but we would still have background-position
to deal with which would keep triggering the heavy operation of re-painting.
I think the best solution, in my humble opinion and I could be completely wrong in approaching it, is to have an img
tag inside your #container
element, provide the image as its src
and remove all the background
related properties from your CSS.
And then move it as well using the same translate
mentioned above. This way, hopefully, you will get the smoothest of results.
Take a look at this updated fiddle or the snippet below.
Snippet:
$(document).ready(function() {
$('#container').css({
'-webkit-transform': 'translateX(0)',
'-moz-transform': 'translateX(0)',
'-o-transform': 'translateX(0)',
'transform': 'translateX(0)'
});
$('#container > img').css({
'-webkit-transform': 'translate(0px, -150px)',
'-moz-transform': 'translate(0px, -150px)',
'-o-transform': 'translate(0px, -150px)',
'transform': 'translate(0px, -150px)'
});
});
#container {
position: absolute;
width: 200px;
height: 200px;
left: 0px;
overflow: hidden;
-webkit-transform: translateX(200px);
-moz-transform: translateX(200px);
-o-transform: translateX(200px);
transform: translateX(200px);
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
}
#container > img {
-webkit-transform: translate(-200px, -150px);
-moz-transform: translate(-200px, -150px);
-o-transform: translate(-200px, -150px);
transform: translate(-200px, -150px);
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
}
body,
html {
margin: 0;
width: 100%;
height: 100%;
}
span {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<span id="container">
<img src="https://images.unsplash.com/photo-1448975750337-b0290d621d6d?crop=entropy&dpr=2&fit=crop&fm=jpg&h=775&ixjsv=2.1.0&ixlib=rb-0.3.5&q=50&w=1450" />
</span>
P.S. As a side note, I am a big fan of GSAP (a JavaScript animation suite of tools). Here is another example using TweenMax
(one of the tools from GSAP) which animates x
property (a shorthand for translateX
within the GSAP world and which also takes care of all the browser prefixes for you behind the scenes) in a more intuitive way using .fromTo()
method.