Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long CSS animation easing (background-position)

I'm trying to animate a background image position smoothly with CSS over a longer period, let's say 60 seconds:

#movingbackground {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Bigsurflowers.jpg/1280px-Bigsurflowers.jpg');
  overflow: hidden;
  background-position: left center;
  animation: zoomin 60s ease-in infinite;
}

@-webkit-keyframes zoomin {
  0% { background-position: 0% center; transform: scale(1.0); }
  50% {background-position: 100% center; transform: scale(1.2); }
  100% { background-position: 0% center; transform: scale(1.0); }
}
@keyframes zoomin {
  0% { background-position: 0% center; transform: scale(1.0); }
  50% {background-position: 100% center; transform: scale(1.2); }
  100% { background-position: 0% center; transform: scale(1.0); }
}
<div id="movingbackground"></div>

The small movements in the beginning and end are "jumping" a few pixel every second instead of moving slowly (may depend on screen size).

The reason for that is probably that there is not enough movement to fill the required number of frames, especially when the animation is eased. As I think I have seen this effect working smoothly somewhere I wonder how to work around this.

Here's a Fiddle as well.

like image 921
user127091 Avatar asked Mar 09 '26 20:03

user127091


2 Answers

Animation of background-position makes browser to do layout, paint and composite.
Re-layout and re-paint are heavy on CPU and cause "jumping".

Instead of that, you might apply your background to pseudo-element (or use <img> in your HTML) and animate its transform property using 3d transformation.

It will make browser to use GPU for the animation and animation will run in composition phase pretty smoothly.

See the snippet below:

html,
body {
  margin: 0;
  padding: 0
}

#movingbackground {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

#movingbackground:before {
  content: '';
  position: absolute;
  top: 0; left: 0; z-index: -1;
  height: 100%;
  width: 200%;
  background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Bigsurflowers.jpg/1280px-Bigsurflowers.jpg) 0 50% / cover;
  animation: zoomin 60s ease-in infinite;
}

@keyframes zoomin {
  50% {
    transform: translateX(-50%) scale(1.2)
  }
}
<div id="movingbackground"></div>
like image 69
Kosh Avatar answered Mar 12 '26 13:03

Kosh


I did some testing and came to the conclusion that it's probably impossible. (At least with transitions or animations)

The problem is the way browsers render images on a screen. The pixels of the image apparently get lined up with those of your screen.

So the picture always "jumps" exactly one pixel at a time.

That means, that the more pixels you have in your image, the more steps it will make. But when using ease-in it will always stutter in the beginning.


As I think I have seen this effect working smoothly somewhere

That was probably not realized with css.

like image 30
Johey Avatar answered Mar 12 '26 12:03

Johey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!