Animate CSS background-position with smooth results (sub-pixel animation)
Asked Answered
C

3

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?

Clementineclementis answered 13/1, 2014 at 9:19 Comment(2)
you know this only works on webkit browsers right?Screeching
@Screeching yeah, and translate is more compatible. Eg. w3schools.com/css/css3_2dtransforms.aspClementineclementis
S
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/

Syphilology answered 13/1, 2014 at 10:1 Comment(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?Guria
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/505Zaremski
@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.Oyer
S
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;
}
Spiritual answered 23/7, 2015 at 19:5 Comment(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?Potvaliant
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.Spiritual
C
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;
}
Contestant answered 13/1, 2014 at 11:39 Comment(1)
Unfortunately the result looks really jerky. Thanks for posting the solution though.Clementineclementis

© 2022 - 2024 — McMap. All rights reserved.