Is it worth worrying about CSS rendering performance? Or should we just not worry about efficiency at all with CSS and just focus on writing elegant or maintainable CSS instead?
This question is intended to be a useful resource for front-end developers on which parts of CSS can actually have a significant impact on device performance, and which devices / browsers or engines may be affected. This is not a question about how to write elegant or maintainable CSS, it's purely about performance (although hopefully what's written here can inform more general articles on best-practice).
Existing evidence
Google and Mozilla have written guidelines on writing efficient CSS and CSSLint's set of rules includes:
Avoid selectors that look like regular expressions .. don't use the complex equality operators to avoid performance penalties
but none of them provide any evidence (that I could find) of the impact these have.
A css-tricks.com article on efficient CSS argues (after outlining a load of efficiency best practices) that we should not .. sacrifice semantics or maintainability for efficient CSS
these days.
A perfection kills blog post suggested that border-radius
and box-shadow
rendered orders of magnitude slower than simpler CSS rules. This was hugely significant in Opera's engine, but insignificant in Webkit. Further, a smashing magazine CSS benchmark found that rendering time for CSS3 display rules was insignificant and significantly faster than rendering the equivalent effect using images.
Know your mobile tested various mobile browsers and found that they all rendered CSS3 equally insignificantly fast (in 12ms) but it looks like they did the tests on a PC, so we can't infer anything about how hand-held devices perform with CSS3 in general.
There are many articles on the internet on how to write efficient CSS. However, I have yet to find any comprehensive evidence that badly considered CSS actually has a significant impact on the rendering time or snappiness of a site.
Background
I offered bounty for this question to try to use the community power of SO to create a useful well-researched resource.
The first thing that comes to mind here is: how clever is the rendering engine you're using?
That, generic as it sounds, matters a lot when questioning the efficiency of CSS rendering/selection. For instance, suppose the first rule in your CSS file is:
So when a very basic engine sees that (and since this is the first rule), it goes and looks at every element in your DOM, and checks for the existence of
class1
in each. Better engines probably map classnames to a list of DOM elements, and use something like a hashtable for efficient lookup.Our example "basic engine" would go and revisit each element in DOM looking for both classes. A cleverer engine will compare
n('class1')
andn('class2')
wheren(str)
is number of elements in DOM with the classstr
, and takes whichever is minimum; suppose that'sclass1
, then passes on all elements withclass1
looking for elements that haveclass2
as well.In any case, modern engines are clever (way more clever than the discussed example above), and shiny new processors can do millions (tens of millions) of operations a second. It's quite unlikely that you have millions of elements in your DOM, so the worst-case performance for any selection (
O(n)
) won't be too bad anyhow.Update:
To get some actual practical illustrative proof, I've decided to do some tests. First of all, to get an idea about how many DOM elements on average we can see in real-world applications, let's take a look at how many elements some popular sites' webpages have:Facebook: ~1900 elements (tested on my personal main page).
Google: ~340 elements (tested on the main page, no search results).
Google: ~950 elements (tested on a search result page).
Yahoo!: ~1400 elements (tested on the main page).
Stackoverflow: ~680 elements (tested on a question page).
AOL: ~1060 elements (tested on the main page).
Wikipedia: ~6000 elements, 2420 of which aren't
spans
oranchors
(Tested on the Wikipedia article about Glee).Twitter: ~270 elements (tested on the main page).
Summing those up, we get an average of ~1500 elements. Now it's time to do some testing. For each test, I generated 1500
divs
(nested within some otherdivs
for some tests), each with appropriate attributes depending on the test.The tests
The styles and elements are all generated using PHP. I've uploaded the PHPs I used, and created an index, so that others can test locally: little link.
Results:
Each test is performed 5 times on three browsers (the average time is reported): Firefox 15.0 (A), Chrome 19.0.1084.1 (B), Internet Explorer 8 (C):
Similar experiments:
Apparently other people have carried out similar experiments; this one has some useful statistics as well: little link.
The bottom line:
Unless you care about saving a few milliseconds when rendering (1ms = 0.001s), don't bother give this too much thought. On the other hand, it's good practice to avoid using complex selectors to select large subsets of elements, as that can make some noticeable difference (as we can see from the test results above). All common CSS selectors are reasonably fast in modern browsers.Suppose you're building a chat page, and you want to style all the messages. You know that each message is in a
div
which has atitle
and is nested within adiv
with a class.chatpage
. It is correct to use.chatpage div[title]
to select the messages, but it's also bad practice efficiency-wise. It's simpler, more maintainable, and more efficient to give all the messages a class and select them using that class.The fancy one-liner conclusion:
Anything within the limits of "yeah, this CSS makes sense" is okay.