Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm using CSS 3D transformations to zoom a div, for example:

-webkit-transform: scale3d(2,2,1); 

The scaling itself works fine in any WebKit browser. However, when using this on Safari (mobile or Windows), the content of the div is not re-rendered. The result is that the content gets blurred after scaling.

This effect only occurs when using 3D transformations. Everything works fine when using

-webkit-transform: scale(2);.

In order to exploit hardware acceleration on iPhone/iPad, it would be nice to use the 3D transformations.

Does anybody know how to tell Safari to re-render a div with the new scale?

like image 317
FatCat123 Avatar asked Jan 09 '11 20:01

FatCat123


2 Answers

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

like image 163
methodofaction Avatar answered Nov 13 '22 12:11

methodofaction


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.

like image 37
Rodrigo Avatar answered Nov 13 '22 12:11

Rodrigo