Scroll Lag with CSS3 box-shadow property? - performance

I added a box-shadow to a section of a page recently to give it the same shadow border effect that is seen on Mac OS X apps. It looked great, but I noticed that scrolling up and down on the page made it lag. I usually only see this on pages that have annoying background images and tons of images and embedded videos plastered all over (cough MySpace cough). I originally decided to use box-shadow since I figured that it would remove the need to use an image, which would remove any possibility of scroll lag.
I know that CSS3 is still new, but is this the reason for the lag? Is the shadow being software rendered or something? When I apply the box shadow to smaller elements, it doesn't lag at all. I'm just wondering if anyone else has experienced this.
I just tried it on the Stack Overflow front page, on the #content div using Firebug with a setting of:
-moz-box-shadow: 1px 1px 10px;
And I did notice some scroll lag afterwards. I am using Firefox 3.5.
My question is, what are some alternatives to using this attribute if I want to add a Mac OS X style border to a section of my page?
On a side note, does anyone know if it is possible to apply the box shadow only to the top, left, and right sides of the element and not the bottom? I tried 1px -1px 10px but it still shows the shadow on the bottom. If I keep decreasing the second offset, it eventually removes the shadow from the bottom but then the top shadow is now way darker and bigger.
And yes, I have seen the articles on box-shadow at:
CSS3 Info
fredericiana's blog

Your best bet would be to use -moz-border-image instead. That should solve both your issues.
E.g. you could use an image like this,
, combined with CSS like this
-moz-border-image: url(shadow.png) 10 / 10px;
to create your shadow. And since you're using an image, you can leave out the bottom shadow as well, if you want.
You're not going to be able to remove the shadow from the bottom using -moz-box-shadow; it's not called "box shadow" for nothing. It applies a shadow to the entire box. You can't specify a shadow for each side separately like with border, say. The best you could do is fiddle around with the placement, blur and spread of the shadow. But that inevitably leads to a darker shadow on the opposite side.
I get the box shadow lag as well when I try it on Stackoverflow. It affects performance on Safari as well when I try -webkit-box-shadow, though it isn't as noticeable as in Firefox. The performance will hopefully improve in the future, but I presume the shadow will always have some impact since as far as I know it is software rendered.

This has been fixed in webkit as of two days ago. :)
https://bugs.webkit.org/show_bug.cgi?id=22102
You can pick up a chromium nightly to try it out.
I looked in FF3.6 and FF4 and don't see terrible scroll performance there, so it might be addressed there as well.

The issue still persists in Chrome for Android as of the current date. Some box-shadow combos result in a poor scrolling performance. In my case stacking two inset box-shadows (e.g. top / bottom) lead to the described problem. The only solution I can provide is to make the box-shadows less complex and try again...that worked for me. That's unsatisfactory but yeah instead u can also use the border-image solution or remove the affected box-shadow completely. Hope this gets fixed soon, finally. Btw the Android Version of Firefox does not have the problems anymore (for my css3). Moreover the desktop versions of both browsers are not affected in my case.

#shadow {
-moz-border-image: url(img.png) 10 / 10px; #Firefox under v15.0#
-webkit-border-image: url(img.png) 10 / 10px; #Safari, Chrome under v15.0, Android & iOS#
-o-border-image: url(img.png) 10 / 10px; #Opera under v15.0#
border-image: url(img.png) 10 / 10px; #IE v11+, other new Browser#
}
Cross browser version for old and new browser.
Simple img: http://i28.tinypic.com/2njzkt1.png
style :fixed for images too overload perfomance browser

Related

Border-radius on an image with a border is different on Firefox and Chrome

This is best explained with images.
Firefox, right:
Chrome, wrong:
jsfiddle.
That is a (fully green) image with 2px (red) border and a border-radius of 6px. In my design, the border is barely visible, so the image looks completely square in Chrome.
Is it possible to achieve the correct result in Chrome without extra markup nor javascript?
I don't believe you can do this with Chrome. Images will extend over the bounds of border-radius, and I think that's the intended behavior (or else they just didn't notice).
When using a div, for example, you can see that the background behaves as it should. You could consider using a div instead of img, and using your source image as the background (and forcing its width and height).
Plainly said: In Chrome, there does not seem to be a way to force your image to be hidden by the border of itself (or even of its container) unless it is set as a background. In fact, the issue has been asked about before, and blogged about as well (and, in fact, patrickzdb's comment there may help you).
Apparently it is a bug in chrome..
I normally apply box-shadow for chrome instead of border.
so, if you don't mind to apply css hack to workaround it without javascript: http://jsfiddle.net/3cuHU/

Safari changing font weights when unrelated animations are running

I'm using css animations on my page and Safari seems to change unrelated font weights elsewhere on the page when animations are running. Any idea why this happens? All other browsers work fine, include webkit ones like Chrome.
I've detailed the bug in a video here - http://www.screenr.com/gZN8
The site is also here - http://airport-r7.appspot.com/ but it might keep changing rapidly.
I'm using compass (#transition-property, #transition-duration) on the arrow icons. No transitions applied on the heading that's flashing. On a Mac - so it might be the hardware acceleration, but I'm still trying to figure it out.
When you trigger GPU compositing (eg, through CSS animation), the browser sends that element to the GPU, but also anything that would appear on top of that element if its top/left properties were changed. This includes any position:relative elements that appear after the animating one.
The solution is to give the animating element position:relative and a z-index that puts it above everything else. That way you get your animation but keep the (superior IMO) sub-pixel font rendering on unrelated elements.
Here's a demo of the problem and solution http://www.youtube.com/watch?v=9Woaz-cKPCE&hd=1
Update: Newer versions of Chrome retain sub-pixel antialiasing on GPU composited elements as long as the element has no transparency, eg has a background with no transparent or semi-transparent pixels. Note that things like border-radius introduce semi-transparent pixels.
Apparently, that's the price you pay for hardware acceleration: all text momentarily turns into images, which causes the drop in render quality.
However, applying html {-webkit-font-smoothing: antialiased} to turn off the sub-pixel anti-aliasing makes this problem go away. That's what I'm doing for now.
UPDATE: Since then, I've also come to learn that this happens only when the browser can't be sure if the section being animated is going to affect the text. This can usually be handled by having the text above (higher z-index than) the elements being animated, and/or making sure the text has a fully opaque background.
I've faced this issue numerous times and have had success adding the following css to the animated element:
z-index: 60000;
position: relative;
It seems it needs both z-index and position to be effective. In my case I was using it with Font Awesome animated spinners.

Webkit not respecting overflow:hidden with border radius

I have a lovely Star Trek Red Alert animation using CSS3. One of my parent elements has a border-radius along with overflow:hidden so that any content is cropped to the shape of the border radius.
This all works fine in Firefox but Webkit browsers leave some child elements hanging outside the cropped area.
Here is my code:
http://jsfiddle.net/doublewombat/EqK6R/embedded/result/
The div with the class name curvedEdges has the border-radius and overflow:hidden. However the blocks left & right of the 'Alert' text hang outside of this radius, even though they are child elements of curvedEdges. Or in plain English, the left and right edges of the animation should be slightly curved (as in Firefox), not dead straight.
So is this a bug in Webkit, or have I got something wrong?
Here it is on YouTube if you don't have a Webkit browser handy...
http://www.youtube.com/watch?v=3vyVy21nWsE
Firstly, what a cool demo!
I had a look around and it seems a problem not on you are having. The second answer to someone else's problem fixed it for me, although this doesn't work for safari. The fix is to use masking:
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
The accepted answer to that same question has another fix, which I think could really help you out, but I couldn't seem to get the right combination of elements and border-radius.
I'd been trying to do the same, and was using border-radius to mask elements to a circle.
I was able to use masking and a radial gradient to achieve the desired affect in Safari 6.0.3 (with transitions in position and size).
Here's the single line of code I added to the container (masking) element:
-webkit-mask-image: -webkit-radial-gradient(circle, white, black);
I thought I would have to use hard color stops, as follows, to get the hard edge:
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
However, it works the same without (perhaps someone can enlighten us on why). The clipping is not as smooth as with border-radius, but it beats the heck out of the image unpredictably exceeding the bounds.
You may need to adjust this for use with older versions of Safari/Chrome etc., I haven't tested it on different versions (aka YMMV).
It appears to be a browser issue as reported on: https://code.google.com/p/chromium/issues/detail?id=157218
Basically, when you apply animation to an element, the browser will handle it in the GPU (Graphics Processing Unit) for performance reasons, while the rest is handled by the CPU. That ends up rendering the animation above the mask.
As a workaround you can try adding an imperceptible transform property, that will also trigger GPU handling for the mask element, promoting it to the same level of the animation:
#redAlert .curvedEdge {
-webkit-transform: rotate(0.000001deg);
}
I guess it may vary depending on browser version, but these other values have also been reported to trigger GPU handling: rotate(0), translateZ(0)
It seems like its an issue with the GPU/hardware compositing. transform: translateZ(0); should fix the issue as well. For more information on this, read http://aerotwist.com/blog/on-translate3d-and-layer-creation-hacks/
-webkit-transform: translateZ(0);
transform: translateZ(0);
I have included vendor prefixes but you can remove them if you want.
Seems its a mixed working fix:
.wrap {
-webkit-transform: translateZ(0);
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
}
http://jsfiddle.net/qWdf6/82/
You could put an absolute positioned div over it with a border-radius and a thick black border, it will block the parts you want too be hidden.
I made a demo for another question about a similar problem in FF3.6: http://jsfiddle.net/vfp3v/15/
border-radius; overflow: hidden, and text is not clipped
Just as a heads up, this fix only worked for me if I applied the mask on a container with border-radius, but no border. Ultimately I ended up with something like this:
<div style="border-radius: 15px; border: 1px solid red;">
<div style="border-radius: 15px; overflow: hidden; -webkit-mask-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);">
<span style="position: relative; left; -20px;">Some stuff that overflows.</span>
</div>
</div>
With a border on the inner div, the clipping wasn't perfect.
Totally weird.
I found another possible solution to this bug, using CSS3 clip-path, but it only works in recent versions of webkit (it seems to work in Chrome 24, but not Safari 6.0.2). The following will clip a circle around the element:
-webkit-clip-path: circle(50%, 50%, 100%);
Hopefully this will be implemented by more browsers soon! It seems like this feature could have a lot of cool applications. Here's a relevant blog post: http://blog.romanliutikov.com/coding/css-clip-path-landed-in-webkit/.

Why is some CSS not working for Firefox?

I've been working on making my website compatible with not only chrome, but firefox as well, and it's not turning out so well as I hoped it to be. Even with Firefox 9 (that i downloaded today), advertised by themselves to be the "best" browser that is compatible with more css---css3 in specific, however there were unexplainable errors, probably on my part, with some non-working css.
My first problem is with gradients. I had two gray-gradient dividers that uses the same gradient code, but produces very different results.
background-image: -moz-linear-gradient(bottom, rgb(58,58,58) 0%, rgb(85,85,85) 100%);
was the one that really worked.
background-image: -moz-linear-gradient(bottom, rgb(42,42,42) 100%, rgb(25,25,25) 0%); however, did not. In fact it showed nothing at all. I put the first one in this one to test if it works, and it did, but this one specifically would not.
Using Firebug, it changed my line of code into: background-image: -moz-linear-gradient(center bottom , #2A2A2A 100%, #191919 0%);
So was there a mistake I made somewhere? Because I can't see the difference between example 1 and 2.
My second error is not CSS3, but it is adding padding:20px; in the tags in a table. it works very well in chrome, but no padding showed up in firefox. Is there an alternative for this other than border properties, because I'm also using borders in the tags.
Thanks again for helping me! I appreciate it a lot, because this bug has been bugging me for the past hour or two, and I still haven't figured anything out.
As you found out yourself, you cannot make a gradient from 100% to %0, so the gradient steps must be ordered with the percentage rising. (even though some browsers seem to display it, you should always keep to the standards!)
Regarding the <tr>, this tag does not take a padding attribute, see https://developer.mozilla.org/en/HTML/Element/tr
Try to achieve what you want using the cellpadding and cellspacing html attributes on the <table> or CSS padding on the <td>s.

Does Firefox/Opera handle positioned/multiple background images?

Having issues getting specific background images to display in Firefox/Opera, all other browsers are playing ball (except obviously IE, for which I've had to compromise).
Currently, Opera won't allow multiple background images like so:
background-image: url('/images/h2_default_bg.png'), url('/images/dashed_bg_default.gif');
background-repeat: no-repeat, repeat-x;
background-position: top left, bottom left;
Also both Firefox and Opera are both being awkward when a background image is positioned in pixels:
background: url('/assets/images/dashed_bg.gif') bottom 2px repeat-x;
Are there any simple workarounds for either of these problems?
Multiple backgrounds are only supported starting from Firefox 3.6 and Opera 10.5. Are those the versions you're testing in? Chrome and Safari already support them, which I presume you mean with "all other browsers ... except obviously IE"
As for your second problem, the spec says this about the background-position syntax:
If two values are given and at least one value is not a keyword, then the first value represents the horizontal position (or offset) and the second represents the vertical position (or offset).
So you've given them in the wrong order. Make it 2px bottom instead.
Currently, Opera won't allow multiple background images like so:
Multiple background images like that are not possible in CSS2 / 2.1, which at the moment we still have to adhere to.
See this quirksmode page on which browsers currently support multiple backgrounds.
As for the other settings, background position definitely works across browsers, I'm not aware of any incompatibilies there. What exactly happens in Firefox and Opera?
As you found out, multiple backgrounds works in all the modern browsers. It does work in Opera as of version 10.5. There is no information on whether IE9 will have it nor if/when IE will ever support it.

Resources