CSS performance relative to translateZ(0) - performance

A number of blogs have expressed the performance gain in 'tricking' the GPU to think that an element is 3D by using transform: translateZ(0) to speed up animations and transitions. I was wondering if there are implications to using this transform in the following manner:
* {
-webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
}

CSS transformations create a new stacking context and containing block, as described in the spec. In plain English, this means that fixed position elements with a transformation applied to them will act more like absolutely positioned elements, and z-index values are likely to get screwed with.
If you take a look at this demo, you'll see what I mean. The second div has a transformation applied to it, meaning that it creates a new stacking context, and the pseudo elements are stacked on top rather than below.
So basically, don't do that. Apply a 3D transformation only when you need the optimization. -webkit-font-smoothing: antialiased; is another way to tap into 3D acceleration without creating these problems, but it only works in Safari.

If you want implications, in some scenarios Google Chrome performance is horrible with hardware acceleration enabled. Oddly enough, changing the "trick" to -webkit-transform: rotateZ(360deg); worked just fine.
I don't believe we ever figured out why.

It forces the browser to use hardware acceleration to access the device’s graphical processing unit (GPU) to make pixels fly. Web applications, on the other hand, run in the context of the browser, which lets the software do most (if not all) of the rendering, resulting in less horsepower for transitions. But the Web has been catching up, and most browser vendors now provide graphical hardware acceleration by means of particular CSS rules.
Using -webkit-transform: translate3d(0,0,0); will kick the GPU into action for the CSS transitions, making them smoother (higher FPS).
Note: translate3d(0,0,0) does nothing in terms of what you see. It moves the object by 0px in x,y and z axis. It's only a technique to force the hardware acceleration.
Good read here: http://www.smashingmagazine.com/2012/06/21/play-with-hardware-accelerated-css/

I can attest to the fact that -webkit-transform: translate3d(0, 0, 0); will mess with the new position: -webkit-sticky; property. With a left drawer navigation pattern that I was working on, the hardware acceleration I wanted with the transform property was messing with the fixed positioning of my top nav bar. I turned off the transform and the positioning worked fine.
Luckily, I seem to have had hardware acceleration on already, because I had -webkit-font-smoothing: antialiased on the html element. I was testing this behavior in iOS7 and Android.

On mobile devices sending everything to the GPU will cause a memory overload and crash the application. I encountered this on an iPad app in Cordova. Best to only send the required items to the GPU, the divs that you're specifically moving around.
Better yet, use the 3d transitions transforms to do the animations like translateX(50px) as opposed to left:50px;

Related

Performance of align-items: stretch vs alternatives

In my current project, there is a performance constraint on tolerable loading times, and test deployments have demonstrated that lag is significant enough for me to look into code optimisation.
While researching on the performance of CSS flexbox, my understanding is that it is faster than both the old flexbox implementation and CSS tables (Source). When comparing between flexbox and the new up-and-coming CSS Grid (Source), grid performs better in 2D layouts, which is only to be expected since it's designed for that as opposed to flex which is designed for 1D layouts.
However, when it comes to 1D layouts, grid performs better than CSS flex when the latter uses align-items: stretch (the default value for this property). When stretch is not used though, flex performs better.
So therein lies the question: stretch alignment is useful but has a significant impact on performance (which is important to me because of my project's system's heavy use of iframes and nested flexboxes within each frame). Will it therefore improve performance if I don't use stretch and replace it with other alternatives (e.g. width: 100% or height: 100% depending on the flex direction) for specific elements that do not already fill up the whole space without stretching?

CSS opacity filter faster than opacity property?

On this html5rocks article, it states that
In general the CSS ‘opacity’ property isn’t hardware accelerated, but some browsers that implement filters using hardware acceleration will accelerate the filter version of opacity for much better performance.
This seems to imply that in performance-intensive applications, one should use the opacity filter instead of the opacity property. For example, I'm rendering a canvas under an image with an opacity property of 0.5. Should I be using the filter instead? How could one measure performance gains when using this filter property, and on what platforms might there be a noticeable improvement?
First, CSS3 filter effects are still a draft standard and their browser support varies. So think twice whether you really need them (e.g., CSS Filters in the Real World article (04.2013) reports rendering artifacts).
Hardware acceleration in Webkit and GPU Accelerated Compositing in Chrome give an overview of their implementations and both suggest there's no discrimination against CSS2 or CSS3 (I'd be surprised if there was).
Second, a review in PC magazine (01.2013) shows results of some online benchmarks by IE and Firefox teams. There are canvas, particle and CSS (rotation) benchmarks. The Maxthon (uses WebKit) and Opera versions tested there do not support acceleration so they give a hint on the performance gain. Regarding the transparency: it's orders of magnitude less computations than resampling so you shouldn't notice any difference for this specific operation.
Paul Irish says here that opacity is one of the few CSS properties that *is* GPU accelerated: https://plus.google.com/+AddyOsmani/posts/aTRerYcZpts
And also, there is a severe lack of support for filters across browsers as can be seen here, though opacity is supported across the board: http://caniuse.com/#search=opacity.
Not to mention the opacity property is just so much easier to use.
I'd stick with what you've got.

CSS3 animations with transform causes blurred elements on Webkit

So I've got some native elements (divs) with various effects applied to them (border-radius, box-shadow and transform: scale()). When I animate them, two weird things happen:
Even though I'm not trying to animate the scale, if I don't put the scale in the animation, it is ignored.
When I put the scale in the animation, Webkit blurs the elements
See the example here: http://jsfiddle.net/trolleymusic/RHeCL/ - the buttons at the bottom will trigger the issues.
The first issue happens in Firefox too, so I'm guessing that it's because that's how the animation spec is supposed to work. Not what I wanted, but ok, I'll live with it.
The second issue is just weird. I know it's to do with 3d transform because if I (just for testing purposes) declare -webkit-perspective or -webkit-transform-style: preserve-3d; on the circle elements, it causes the blur issue as well. My confusion is that I'm not trying to transform the z index as all, and I have also tried the animations using purely translateY instead of translate.
It happens in Chrome (18), Chrome Canary (20) and Safari (5.1.2 & 5.1.4).
So, am I right in what I think is happening? And how can I avoid the blurriness?
Worst-case scenario: I can just use different sizes for the elements instead of scaling them, that's not really a problem - but I thought this would be a more elegant solution and now this issue has cropped up.
Refer to this answer as to why it's blurring the element: https://stackoverflow.com/a/4847445/814647
Summary of the above: WebKit is taking the original size/CSS before animating, and treating it as an image, THEN scales it up, producing the blurriness.
Solution: Make initial size the largest scale you're going to, and start it initially with a lower scale (so in your case you'd want to up the size by 5, and set the initial scale to 0.2)
UPDATE
The reason it ignores the current scale from what I understand is because you're not specifically setting JUST the translate (I'm looking up the CSS for it now). When you run -webkit-animation, it's resetting all your current transforms (scale), so you need to make sure that you have your scales in there. I'm looking up the css to change so it only changes just the position:
The best way I found is to wait the animation is complete, then apply the transforms directly to the element and remove the animation class. Something like this works for me, producing no glitches:
$m.bindOnce($m('win-text'), 'webkitAnimationEnd', function(){ //avoid blurred problem with animating scale property in webkit
$m('win-text').style.webkitTransform = 'scale(1.5) translateY(-60px)';
$m.removeClass($m('win-text'), 'final');
});
I'm using a different library than jQuery, but you get the idea.

CSS3 background-size property causing extreme performance issues in ff5

I've been putting a page together today and thought that I'd implement a striped background using CSS3. All seemed fine in all browsers except for Firefox. (I'm using 5.01 but checked in 5.0 too)
The code is simple enough:
body {
background-color: #ebeced;
background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%,
transparent 25%,transparent 50%, rgba(255, 255, 255, .2) 50%,
rgba(255, 255, 255, .2) 75%,transparent 75%, transparent);
background-size:6px 6px;
}
Works great in Chrome and opera but it practically crashes FF.
Obviously I know that I can achieve this effect with a repeating background image but I was wondering if anyone else had a similar issue or is it just teething problems with CSS3 again ;)
Testing in jsfiddle produces the same issues, I didn't make a fiddle as I didn't want to be responsible for crashing you!
Oh and it's not a slow pc issue, I'm on an i7, 8gb ram, blah blah.
I believe it to be a problem with the background-size property as if you increase this or remove it entirely then the issue is resolved, however it's not suitable for me unless I can use background-size.
I am pretty sure I know what the problem is.
The performance problem is not very apparent for me, but I am on a new quad-core. What I do see is that when I create a blank page and put that css in there, then if I resize the browser, the redraw is a little clunky.
The problem comes from the fact that you are combining drawing CSS3 gradients with tiling that gradient at a very small size (6px). This means that for every 1000 sq.px of page real estate, the gradient will tile 27,777 times [1000/6 squared]. That is a ton! A smart browser would draw the gradient once and then tile it. It seems like Firefox may draw the gradient every time. If that is the case, that would indeed be a bug. If I modify the background size property to something larger, like 20px then I no longer see a performance problem, but others will. If you don't want your users experiencing these kinds of problems, I would say that you should stay away from this combination because slower computers will still have problems when you don't see any.
The easy fix is to not use the css3 gradients. Just create an image - browsers are good at tiling those. Even with images, it is sometimes better to use larger images ...
Early versions of Netscape Navigator used to ignore backgrounds if they were smaller than 40x40 pixels. I remember discovering that the cause of the bug I was trying to solve, and realizing that even though it seemed nice to be able to use a 1x20 image for a background because that would be the minimum file size, it was not the best choice for performance because it creates much more rendering work for the browser. Instead, I create a larger 50x20 version of the image. The effect is the same, but it saves some processing time.
Have you tried adding...
-moz-background-size:6px 6px;
...to your css?

text-shadow (and other css3) causes scroll lag

I've noticed that the more I use certain CSS3 elements (namely box-shadow and text-shadow) the more scroll lag exists on a page. I notice the problem on both FF4 and Chrome 10. Is there any good way to measure this or reduce it? I want good performance, but I also want to be able to use the shadows to create dimensionality between the various elements.
Thanks!
I've found the two biggest offenders (as far as performance goes) are the blur amount of your shadows and whether you're using any alphas (rgba, hsl, etc).
Hardware acceleration is key to using any of the css3 goodies and maintaining acceptable performance. Webkit (not sure about FF4) won't even use the GPU unless you specifically ask for a three-dimensional operation. You can kick in the GPU for any element by simply applying a 0-pixel 3d transform:
-webkit-transform: translate3d(0,0,0);
/* OR */
-webkit-transform: translateZ(0);
Paul Irish has a great talk on css3 performance and using webkits dev flags to debug GPU rendering.
From terminal (OS X), you can launch Safari with the GPU rendering debug flag with this:
CA_COLOR_OPAQUE=1 /Applications/Safari.app/Contents/MacOS/Safari
This will show you (in translucent red) which DOM regions are being rendered on the GPU and which ones are rendered by the CPU like this.

Resources