CSS keyframe animation with translation transform snaps to whole pixels in IE 10 and Firefox

Strille picture Strille · May 29, 2013 · Viewed 17.5k times · Source

It appears both IE 10 and Firefox snaps elements to whole pixels when animating their position using translate 2d transform in a css keyframe animation.

Chrome and Safari does not, which looks a lot better when animating subtle movements.

The animation is done the following way:

@keyframes bobbingAnim {
   0% {
       transform: translate(0px, 0px);
       animation-timing-function:ease-in-out
   }

   50% {
       transform: translate(0px, 12px);
       animation-timing-function:ease-in-out
   }

   100% {
       transform: translate(0px, 0px);
       animation-timing-function:ease-in-out
   }
}

Here's an example of what I mean:

http://jsfiddle.net/yZgTM/.

Just open it in Chrome and IE 10 (or Firefox) and you should notice the difference in smoothness of the motion.

I realise there might be many factors affecting this behaviour such as if the element is drawn with hardware acceleration or not.

Does anyone know of a fix to try to force browsers to always draw the elements on subpixels?

I found this similar question, but the answer was to animate using a translate transform, which is exactly what I'm doing: CSS3 Transitions 'snap to pixel'.

Update: After playing around a bit I found a fix for Firefox, doesn't do anything in IE 10 though. The trick is to scale down the element ever so slightly and use translate3d with a 1px offset in the Z-axis:

@keyframes bobbingAnim {
   0% {
       transform: scale(0.999, 0.999) translate3d(0px, 0px, 1px);
       animation-timing-function:ease-in-out
   }

   50% {
       transform: scale(0.999, 0.999) translate3d(0px, 12px, 1px);
       animation-timing-function:ease-in-out
   }

   100% {
       transform: scale(0.999, 0.999) translate3d(0px, 0px, 1px);
       animation-timing-function:ease-in-out
   }
}

Answer

wick3d picture wick3d · Jun 15, 2016

I love your question! Good job in noticing the pixel-snap in firefox and IE10.

I've researched this subject a while ago and I advise you to check the GSAP forums, as they contain a lot of useful information on web animations.

Here's a topic regarding IE10 pixel-snap issue.

What you need to do is add a minimal rotation to the element. This is so IE and Firefox will redraw it in a different way - which will stop pixel-snap for good :)

Tyr this:

@keyframes bobbingAnim {
  0% {
   transform: translate(0px, 0px) rotateZ(0.001deg);  
   animation-timing-function:ease-in-out
  }

  50% {
    transform: translate(0px, 12px) rotateZ(0.001deg);
    animation-timing-function:ease-in-out
  }

  100% {
   transform: translate(0px, 0px) rotateZ(0.001deg);
   animation-timing-function:ease-in-out
  }
}