I'm using Isotope (isotope.metafizzy.co) with a Masonry Horizontal layout. Example:
http://codepen.io/desandro/pen/oCiAD
It works just fine, but I'm curious as to why the library sets the left/right and top/bottom properties instead of using transforms. It's my understanding that using 3D such as
transform: translateZ(0);
or
transform: translate3d(0,0,0);
will force the element onto another layer, triggering GPU rendering and better performance. I realize this is probably done intentionally, but I'm not clear as to why.
Have browsers improved and is this no longer necessary? If not, is there a way to enable 3d transforms in Isotope?
Thanks in advance.
I think one of the reasons could be that Webkit treats 3d transformed elements as textures instead of vectors in order to provide hardware 3d acceleration which could cause a blurry text or anti-aliasing issues.
Example:
http://jsfiddle.net/gibbok/ccw7vvvg/
-webkit-transform: translate3d(0px, 100px, 0px);
I know that sometimes browsers will GPU accelerate a CSS transform. But when does that happen, and is there a way to force GPU acceleration for a smooth animation?
this article
Most modern browsers support GPU acceleration, but they only use it when they think a DOM element will benefit from it. The strongest indication is that a 3D transformation is being applied. So use the 3D-equivalent transform. For example, instead of transform: translateX(50px), use transform: translate3d(50px, 0, 0). See this article for more information.
You can use the css "will-change" property:
will-change: transform;
Some css properties which are GPU accelerated (not always):
filter
opacity
transform
I am making an app and realised that it is best to hardware accelerate animations.
I wanted to use jQuery animate enhanced, which works but I feel I want a better grasp on the whole idea of hardware acceleration:
When moving a div using top/left positioning for example using jQuery, will it automatically be hardware accelerated by adding transform: translate3d(0, 0, 0); ?
Will this hardware accelerate anything? Also, what about animation keyframes? Will you need to add a transform to an animation for it to be hardware accelerated?
Paul Irish wrote a great, in-depth breakdown of this very thing.
Usually 3d translation will trigger the GPU, if it doesn't, it's no big deal, it still works. Using translate over left/top coordinates is usually better performance-wise as well. I'm not sure about the animation keyframes part of the question though.
I know that you can force GPU acceleration to achieve smooth animation of elements across the screen by applying a transition to the 'transform' property, e.g.:
elem.style.transition = 'all 3s ease-out';
elem.style.transform = 'translateX(600px)';
But I was wondering what would happen if you replaced the second line with:
elem.style.left = '600px';
Would/could GPU acceleration kick in for the "left" (or "top") property, or does it have to be on the transform property? It seems to me that it should be GPU accelerate-able, but I can't glean a final answer from any of the documentation I've read.
It's not accelerated. You have to use the specific CSS3 properties for it to be accelerateable. I think you'll find these links interesting:
http://www.html5rocks.com/en/tutorials/speed/html5/
http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
Does animating the value of a CSS3 transform with javascript rule out hardware acceleration?
The consensus I've gathered is that only the translate3d property is hardware accelerated on mobile devices such as Mobile Safari.
Further Reading.
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?
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
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.
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.
I couldn't find a fix for making zoom-ins not blur in Safari (desktop v7.0.2 and the one included in iOS 6.1.3 and 7.0.6) but I did at some point, notice that I got a sharp png when I set the scale to 5. I don't know why, since that version of my code is lost in all the subsequent changes I made. All other scale factors were blurry.
Since the iPhone and iPad are target devices for this project I ended up abandoning scale transform and animating image height instead. I'm disappointed that the Safari team decided to implement transforms in a way that make them an unviable option in so many cases.
Hmmm... I'm getting the same issue trying to scale up google maps images (hidpi) with Chrome 53.
The only solution I've found so far is to hide the image (or a div that contains the images) and then show it again. Can be with opacity=0 or visibility=hidden, but it actually has to be invisible for at least a frame or two.
This, BTW, isn't even a 3d transform. Just 2D stuff.
Hmmm... I'm getting the same issue trying to scale up google maps images (hidpi) with Chrome 53.
One solution is to hide (opacity, visibility) the image for a few frames (or a container wrapping the image/images/whatever it is)... the better solution which I found in another post on SO was this (issued on the containing DIV):
e.style.transform = 'translateZ(0) scale(1.0, 1.0)'
BTW, my stuff was just ordinary 2d stuff, the translateZ seems to make the difference though, even though I never touched anything 3d.