Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to optimize CSS animatons (scale, rotate, blur)

The following HTML example consists of two pictures; one background, the other is an object. Both are animated using scale and rotate. On full HD monitors it tends to be choppy. When you look at the performance in Firefox it gets about 20 fps.

First I used jQuery; to improve performance I chose CSS, but it's still not perfect. In order to reproduce the problem go to full screen. How can I make it better?

.html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #121212;
}

.maincontainer {
  width: 100%;
  padding-bottom: 100%;
  position: fixed;
  overflow: hidden;
}

.bg {
  background-image: url(http://wallpaper-gallery.net/images/beautiful-pictures-of-nature/beautiful-pictures-of-nature-2.jpg);
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: -99;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  background-position: top;
  background-size: 100% auto;
  background-repeat: no-repeat;
}

.bg2 {
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: -99;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  background-position: top;
  background-size: 100% auto;
  background-repeat: no-repeat;
}

.rain {
  background-image: url(https://media.giphy.com/media/OvFQrZk8b5N0Q/source.gif);
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: -1;
  -webkit-filter: blur(1px);
}

.animate-bg {
  -webkit-animation-name: animateBg;
  animation-name: animateBg;
}

.animate {
  -webkit-animation-duration: 35000;
  animation-duration: 35000ms;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
  -webkit-animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-iteration-count: infinite;
}


/* Zoom in Keyframes */

@-webkit-keyframes animateBg {
  0% {
    transform: scale(1) rotate(0deg);
  }
  50% {
    transform: scale(1.3) rotate(4deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

@keyframes animateBg {
  0% {
    transform: scale(1) rotate(0deg);
  }
  50% {
    transform: scale(1.3) rotate(4deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}


/*End of Zoom in Keyframes */

.eagle {
  background-image: url(https://pngriver.com/wp-content/uploads/2018/04/Download-Flying-Eagle-PNG-Image.png);
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: 900;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  background-position: top;
  background-size: 100% auto;
  background-repeat: no-repeat;
}

.animate-eagle {
  -webkit-animation-duration: 35000;
  animation-duration: 35000ms;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
  -webkit-animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-iteration-count: infinite;
  -webkit-animation-name: animateeagle;
  animation-name: animateeagle;
}


/* Zoom in Keyframes */

@-webkit-keyframes animateeagle {
  0% {
    transform: scale(0.8) rotate(0deg);
  }
  30% {
    transform: scale(1.05) rotate(-2deg);
  }
  50% {
    transform: scale(1.1) rotate(0deg);
  }
  80% {
    transform: scale(1.05) rotate(2deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

@keyframes animateeagle {
  0% {
    transform: scale(1) rotate(0deg);
  }
  30% {
    transform: scale(1.05) rotate(-2deg);
  }
  50% {
    transform: scale(1.1) rotate(0deg);
  }
  80% {
    transform: scale(1.05) rotate(2deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}


/*End of Zoom in Keyframes */

.blur {
  animation: blur 5000ms;
}

@keyframes blur {
  0% {
    -webkit-filter: blur(0px);
  }
  20% {
    -webkit-filter: blur(3px);
  }
  40% {
    -webkit-filter: blur(5px);
  }
  60% {
    -webkit-filter: blur(7px);
  }
  80% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}

@-webkit-keyframes blur {
  0% {
    -webkit-filter: blur(0px);
  }
  20% {
    -webkit-filter: blur(3px);
  }
  40% {
    -webkit-filter: blur(5px);
  }
  60% {
    -webkit-filter: blur(7px);
  }
  80% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}

.unblur {
  animation: unblur 1000ms;
}

@keyframes unblur {
  0% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}

@-webkit-keyframes unblur {
  0% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}
<div class="maincontainer">

  <div id="bg2" class="bg2">
    <div id="bg" class="bg animate animate-bg">
      <div class="rain"></div>
      <div class="drops"></div>
    </div>
  </div>

  <div id="eagle">
    <div class="eagle animate-eagle">
    </div>
  </div>
</div>

The suggested duplicate question isn't related because I don't see how this can be solved with canvas.

like image 551
Milos Avatar asked Aug 25 '17 17:08

Milos


People also ask

How do you scale an animation?

Now, let’s look at the three most important ways that we can scale animations: scaling with responsive units, proportional scaling, and adaptive scaling. When we use responsive units like % or em, our animations automatically resize themselves based on the parent because their values change as their parent’s do.

How are CSS animations handled by the browser?

CSS animations are handled by the browser's compositor thread rather than the main thread responsible for painting and styling. Consequently, such animations are unaffected by the main thread's more expensive tasks.

How to keep responsive animation proportional while scaling it?

There are three main ways we can keep our responsive animation proportional while scaling it. 1. Size based on the width To keep an element sized based on the width of the container, we can use the following approach:

How do I improve the performance of my website animations?

Delay all animations by a fraction of a second Since the browser is very busy when your page begins loading, delaying all animations until a few hundred milliseconds after the initial load event can make a noticeable difference in overall page performance. 4. Don't bind CSS animations to scroll


2 Answers

That's because you're blurring an animated GIF in real-time.

Remove -webkit-filter: blur(1px); and the lag is gone.

I tried recreating the rain effect with a canvas element but got the same result so the GIF is not the problem here.

The issue is that Firefox seems to be struggling with the blur filter on animated elements.

(Not really an answer, but too long for a comment)

like image 124
Etienne Martin Avatar answered Sep 30 '22 20:09

Etienne Martin


Have a look at the will-change attribute, potentially this may help you get it a bit smoother, you can read about it here

it doesn't have the greatest browser support thats the only thing.

I suspect your 1px blur on the rain is probably quite intensive, you are bluring something that is constantly changing. I can't quite see where you are using the .blur class and related animation, but that will be quite expensive for performance.

transform: translate3d(0,0,0); as Robert Moore suggests helps webkit particularly to use hardware acceleration, you can read about it here however in this instance as you are using filters these are already taking advantage of hardware acceleration

like image 20
Chris Warnes Avatar answered Sep 30 '22 21:09

Chris Warnes