CSS3 background-size property causing extreme performance issues in ff5 - firefox

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?

Related

Disable anti-aliasing in Chrome / Webkit

Is there a way to disable antialiasing for images in Chrome/Webkit? For performance reasons, I'd like to not have the browser smooth images larger than the actual files.
Image interpolation mode in Chrome/Safari? mentions this problem from a year and a half ago, so hopefully Webkit has added some sort of support since then.
Edit: Upon further research, Using nearest-neighbor with CSS zoom on canvas (and img) seems to go further into this, but isn't clear on exactly what works.

CSS performance relative to translateZ(0)

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;

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.

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.

Are modern browsers good at scaling images down nowadays?

Back in the old days, one would always need to scale images in Photoshop, because the browsers did a terrible job of it. Firefox now seems to scale images smaller quite nicely. Do the other browsers do a nice job too?
Internet Explorer 7 doesn't do so well, but IE8 does. You can change IE7 to use the better method from IE8 with a simple line of CSS.
img { -ms-interpolation-mode: bicubic; }
P.S. I found this out when working on an intranet page where bandwidth wasn't a problem. For something on the internet I would seriously consider resizing the image to reduce the number of bytes.
If you're asking whether or not you're safe to display large images in small areas on a webpage, I wouldn't risk it: resize the image prior to posting/let your framework resize the image. You'll save the client from downloading a huge file, and you'll know exactly how the image will display.
Most modern browsers are good at scaling images, although none will be as good as a proper graphics application.
However if you have a graphic you are scaling to be smaller it still has to be downloaded before scaling it, so it is better to have a small one if you can, especially if you have mobile clients

Resources