Jump to content
Search Community

Chrome bug: When I scale an element with background image, the image flickers

RolandSoos test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts



I have an issue and I was unable to find solution for this case.


In this example, the image is flickering when it scaled down with a smooth animation: 


When I add as an img element, it looks good during the transition: 

See the Pen pPyvdp by anon (@anon) on CodePen


It happens in the latest Chrome and Opera too. Do you have any suggestion to make it smooth with the background image?

See the Pen bWpNYq by anon (@anon) on CodePen

Link to comment
Share on other sites

Hello RolandSoos and welcome to the GreenSock Forum!


The issue you describe is a webkit bug that affects scale and along with the CSS property background-image


Its discussed in this topic Chrome 49 - Janky GSAP: https://greensock.com/forums/topic/13875-chrome-49-janky-gsap


webkit has a bug were if you animate above a scale factor of 1, in your case 1.1 you will start to see jank (lost frames) and jitter (shake rattle and roll)


You can either opt for using a <img> tag instead that is not affected by  this webkit bug, but that might not be feasible in your project.


Or you can add the following CSS properties to your CSS div {} rule like i discussed in that same topic link above:



div {
  width: 100%;
  height: 100%;
  background-position: 50% 50%;
  background-image: url("https://smartslider3.com/wp-content/uploads/2015/10/slide52.jpg");
  background-size: cover;
  -webkit-backface-visibility: hidden; /* add to fix webkit bug jitter */
  -webkit-transform: perspective(1000px); /* add to fix webkit bug jitter */

And also add a slight rotation to your tween so it forces GSAP to animate using matrix3d() instead of matrix() or translate3d(), for better performance:

TweenLite.fromTo('div', 10, {
  scale: 1.1,
  rotation: 0.01 /* add to force matrix3d() */
}, {
  scale: 1,
  rotation: 0.01 /* add to force matrix3d() */

Try this with the changes i advised above


See the Pen aWNvVL by jonathan (@jonathan) on CodePen


See if that helps :)

  • Like 1
Link to comment
Share on other sites

I tested on Windows 10 and Windows 7 on latest Chrome (57.0.2987.133 and  58.0.3029.81) and no longer saw jitter when viewing my codepen.

  • Are you seeing this on Chrome Windows 10 or 7.. or on latest Chrome on Mac?

It is very important.. that anytime you animate an element the it should always have the CSS property..  position: relative or even better position: absolute. That will allow your element to be outside the flow of document, and is required to animate properly so it doesn't effect the elements around it


Also keep in mind that i used transform: perspective(1000px) since that will apply to the element itself. Whereas you changed it to using the set() method to use standalone perspective() CSS property, which only applies to the children of div only. But your div has know children so it wont apply perspective properly.


CSS syntax = GSAP syntax


Link to comment
Share on other sites

I'm not seeing the jitter i tried on both real PC, Windows 7 and Windows 10 in latest Chrome 57, no virtual environment. Its smooth on my end.


For that type of kenburns effect you should leave position absolute, but that is standard anytime you animate with transforms.


You should try it outside of codepen since codepen is running it through an iframe and has issues on there site from time to time.




I did test again with full restart and in Chrome 58 and i did see the jitter towards the end of the animation. So this looks like Google Chrome devs reintroduced the same bug from Chrome 49.


So this is not a GSAP bug but a recurring Chrome 49 bug discussed in this topic:




The bug report for this is a on going webkit Chrome bug, and the webkit bug report be found here:




Before you could fix it with perspective and backface-visibility but it looks like Google broke it for the 100th time, very frustrating! Sorry for this but unfortunately this is Chrome browser bug that has been around even since Chrome 21, that GSAP has know control of :(

  • Like 1
Link to comment
Share on other sites

And what is your personal suggestion based on your experience?

Can we count on chromium developers that this will be fixed in short time or I should stick with css transition for this special animation?


Ps.: it is strange that sometimes works fine and sometimes not as you have to restart your browser to see the flicker....

Link to comment
Share on other sites

This is a two edged sword, Chrome devs have a habit of fixing but then breaking again as seen in that Chrome 49 janky topic.


If you want to use GSAP try switching to using an actual <img> tag instead of using a CSS background-image. Since this webkit bug affects using CSS property transform scale with the CSS property background-image.


See if that helps!

  • Like 2
Link to comment
Share on other sites

Very annoying indeed! I noticed that Google has been using the will-change property in a lot of their animations with Polymer, so I figured I might as well do the same. I'm sure Google is going to break it a couple months down the road, but for now it works.

  • Like 3
Link to comment
Share on other sites

Well, they changed their motto from "Don't be evil." to "Do the right thing."


Of course, neither motto says anything about being annoying, breaking things and making us all work a little bit harder. Maybe that's the right thing to them?  :blink:

  • Like 2
Link to comment
Share on other sites

Well, my local solution was a fallback to CSS transitions as this much feature was enough for that animation.

  .n2noselftransition {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
        function CSSTransitionFromTo($el, duration, from, to) {
            this.startTime = -1;
            this.currentProgress = 0;
            this.$el = $el;
            this.duration = duration;
            this.from = from;
            this.from.immediateRender = true;
            this.to = to;
            this.$el.css('transition', 'all ' + this.duration + 's');

        CSSTransitionFromTo.prototype.pause = function (at) {
            if (at == 0) {
                TweenLite.set(this.$el, this.from);

        CSSTransitionFromTo.prototype.play = function () {

            this.startTime = $.now();
            TweenLite.set(this.$el, this.to);


        CSSTransitionFromTo.prototype.progress = function (at) {
            return ($.now() - this.startTime) / this.duration / 1000;
Link to comment
Share on other sites

  • 2 years later...
  • 4 months later...
  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...