27

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?

Jayden Lawson
  • 2,154
  • 2
  • 21
  • 24

3 Answers3

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/

TylerH
  • 20,799
  • 66
  • 75
  • 101
Slawa Eremin
  • 5,264
  • 18
  • 28
  • 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 Jun 02 '15 at 16:14
  • 1
    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: http://jsfiddle.net/5pVr4/505/ – Oriol Jul 24 '15 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 Jul 20 '17 at 07:02
11

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;
}
Bruno Muller
  • 221
  • 2
  • 8
  • 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? – user2513846 Mar 10 '16 at 05:18
  • You can do something like this: http://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. – Bruno Muller Mar 10 '16 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;
}
Surjith S M
  • 6,642
  • 2
  • 31
  • 50