Strille
Strille

Reputation: 5781

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

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
   }
}

Upvotes: 16

Views: 29892

Answers (3)

wick3d
wick3d

Reputation: 672

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
  }
}

Upvotes: 7

Zanderi
Zanderi

Reputation: 917

@Nemanja is correct you will find that if you tweak the speed you will see better results this is fairly typical with css animations. Also it doesn't really make a difference in this case if you enable hardware acceleration. I tidied up the code a little bit and ran it without any issues, i do not have ie10; However, I have 11. You may have to just remove the second transform of translateZ if it doesn't run in 10

body {
    background-color: #ccc;
}

.bobbing {
    position: absolute;  
    animation: bobbingAnim ease-in-out .5s infinite;
    -moz-animation: bobbingAnim ease-in-out .5s infinite;
    -webkit-animation: bobbingAnim ease-in-out .5s infinite;    
}

.bobbing.text {
    font-size: 50px;
    color: #000;
    left: 30px;
    top: 30px;
}

.bobbing.image {
    left: 30px;
    top: 150px;
    background: url(http://placehold.it/300x100/aa0000&text=Bobbing+image) 50% 50% no-repeat;
    width: 310px;
    height: 110px;
}

@keyframes bobbingAnim {
   50% {
       transform: translate(0, 12px) translateZ(0);       
   }
}

@-webkit-keyframes bobbingAnim {
   50% {
       -webkit-transform: translate3d(0, 12px, 0);       
   }
}

@-moz-keyframes bobbingAnim {
   50% {
       -moz-transform: translate3d(0, 12px, 0);       
   }
}

Upvotes: 0

Nemanja
Nemanja

Reputation: 594

There cant be half a pixel movement, there is no such thing.

Your problem is the speed and smoothness of the animation, not the "pixel snapping".

Upvotes: -4

Related Questions