How to force re-render after a WebKit 3D transform in Safari

Solution 1:

The reason why the text is blurry is because Webkit is treating the text as an image, I guess it's the price of being hardware accelerated. I'm assuming you are using transitions or animation keyframes in your ui, otherwise the performance gains are negligible and you should switch to non-3d transforms.

You can either:

• Add an eventlistener for transitionend and then replace the 3d transform for a standard transform, such as...

element.addEventListener("transitionend", function() {
  element.style.webkitTransform = 'scale(2,2)'
},false);

• Since Webkit treats stuff as an image, it's better to start big and scale down. So, write your css in your "end state" and scale it down for your normal state...

 #div {
  width: 200px; /*double of what you really need*/
  height: 200px; /*double of what you really need*/
  webkit-transform: scale3d(0.5, 0.5, 1);
}

 #div:hover {
  webkit-transform: scale3d(1, 1, 1);
}

And you get a crispy text on hover. I made a demo here (works on iOS too):

http://duopixel.com/stack/scale.html

Solution 2:

I found when trying to force a redraw of a div in safari for other reasons (recalculate text-overflow on hover), that is simple:

selector {
    /* your rules here */
}
selector:hover {
    /* your rules here */
}
selector:hover:after {
    content:"";
}

I did something on hover that changes the padding to accommodate some buttons, but in safari/chrome it doesn't recalculate the content correctly, adding the :after pseudo-class did the trick.

Solution 3:

I'm trying to do the same thing. I think what's happening here is that Safari is just scaling pixels. That is, it does all its "normal" browser rendering and then scales the pixels of the result.

Example: Place a relatively high quality image (say 1000x1000 pixels) in a small div (200x200 pixels) and set the image to 100% width and height. When you 3D transform the div to scale 5 times, the result will be blurry in Safari and crisp in Chrome. Use a 2D transform and the image will appear crisp in both.

A workaround is to convert to a 2D transform after you are done with the 3D. However, I've found there is a slight delay when converting between transforms so this isn't working too well for me.