31

I'm trying to animate the background-position of a div, slowly, but without it having jerky movement. You can see the result of my current efforts here:

http://jsfiddle.net/5pVr4/2/

@-webkit-keyframes MOVE-BG {
    from {
        background-position: 0% 0%
    }
    to { 
        background-position: 187% 0%
    }
}

#content {
    width: 100%;
    height: 300px;
    background: url(http://www.gstatic.com/webp/gallery/1.jpg) 0% 0% repeat;
    text-align: center;
    font-size: 26px;
    color: #000;

    -webkit-animation-name: MOVE-BG;
    -webkit-animation-duration: 100s;
    -webkit-animation-timing-function: linear;
    -webkit-animation-iteration-count: infinite;
}

I have been at this for hours and can't find anything that will animate slowly and smoothly at a sub-pixel level. My current example was made from the example code on this page: http://css-tricks.com/parallax-background-css3/

The smoothness of animation I'm after can be seen on this page's translate() example:

http://css-tricks.com/tale-of-animation-performance/

If it can't be done with the background-position, is there a way to fake the repeating background with multiple divs and move those divs using translate?

2

3 Answers 3

31

Checkout this example:

#content {
  height: 300px;
  text-align: center;
  font-size: 26px;
  color: #000;
  position:relative;
}
.bg{
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: -1;
  background: url(http://www.gstatic.com/webp/gallery/1.jpg) 0% 0% repeat;
  animation-name: MOVE-BG;
  animation-duration: 100s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@keyframes MOVE-BG {
   from {
     transform: translateX(0);
   }
   to { 
     transform: translateX(-187%);
   }
}
<div id="content">Foreground content
  <div class="bg"></div>
</div>

http://jsfiddle.net/5pVr4/4/

3
  • both answers here are not smooth. they lag a little sometimes. i need completely smooth scrolling... hw acc with 3d or Z doesn't do anything, nor does any other "tricky" css-attr smooth things out. is it possible anyway somehow?
    – Guntram
    Commented Jun 2, 2015 at 16:14
  • 2
    The key advantage to CSS3 animations over script-driven animations is performance (hardware accelerated) and predictability (browser is in control and thus optimizes the process). Also, updated the result page to make it cross-browser compatible: jsfiddle.net/5pVr4/505
    – Oriol
    Commented Jul 24, 2015 at 18:57
  • @SlawaEremkin, the solutions work great if you want to repeat a single image twice to give the illusion of infinite. However, this technique would not work for a background image pattern. I would like the same effect, but with a pattern. The current CSS solution is jerky which is animating the background position via CSS transition.
    – Awin
    Commented Jul 20, 2017 at 7:02
13

Animating background-position will cause some performance issues. Browsers will animate transform properties much cheaply, including translate.

Here is an example using translate for an infinite slide animation (without prefixes):

http://jsfiddle.net/brunomuller/5pVr4/504/

@-webkit-keyframes bg-slide {
    from { transform: translateX(0); }
    to { transform: translateX(-50%); }
}

.wrapper {
    position:relative;
    width:400px;
    height: 300px;
    overflow:hidden;
}

.content {
    position: relative;
    text-align: center;
    font-size: 26px;
    color: #000;
}

.bg {
    width: 200%;
    background: url(http://www.gstatic.com/webp/gallery/1.jpg) repeat-x;
    position:absolute;
    top: 0;
    bottom: 0;
    left: 0;
    animation: bg-slide 20s linear infinite;
}
2
  • Hi bruno, how can I edit this to move also in a diagonal? so from right to left like it is now plus a slightly diagonal in the same direction? Commented Mar 10, 2016 at 5:18
  • You can do something like this: jsfiddle.net/5pVr4/723 I'm using a square pattern and animating a single element, so the diagonal animation will be the same horizontally and vertically. If you want it to move faster horizontally and slower vertically you can nest the elements and use different timings for each of them. Other possibility is to use a pattern with a different aspect ratio. Commented Mar 10, 2016 at 13:41
2

You should adjust your HTML and CSS little bit

Working Demo

HTML

<div id="wrapper">
    <div id="page">
    Foreground content
</div>

<div id="content"> </div>
</div>

CSS

@-webkit-keyframes MOVE-BG {
    from { left: 0; }
    to { left: -2000px; }
}

#wrapper {
    position:relative;
    width:800px;
    height: 300px;
    overflow:hidden;
}

#page {
    text-align: center;
    font-size: 26px;
    color: #000;
}

#content {
    width: 2000px;
    height: 300px;
    background: url(http://www.gstatic.com/webp/gallery/1.jpg) 0% 0% repeat;
    position:absolute;
    top: 0;
    left: 0;
    z-index:-1;
    -webkit-animation-name: MOVE-BG;
    -webkit-animation-duration: 100s;
    -webkit-animation-timing-function: linear;
    -webkit-animation-iteration-count: infinite;
}
1
  • Unfortunately the result looks really jerky. Thanks for posting the solution though. Commented Aug 19, 2014 at 13:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.