Efficient and Inefficient CSS Selectors (According to Google, Pagespeed ...)

Efficient and inefficient CSS selectors (according to Google, PageSpeed ...)

Have a look at this recent post by Jonathan Snook: http://snook.ca/archives/html_and_css/css-parent-selectors

You'll see how browsers evaluate expressions and the reasoning behind why certain selectors are inefficient.

A relevant quote from the post:

CSS gets evaluated from right to left.


To determine whether a CSS rule
applies to a particular element, it
starts from the right of the rule and
works it's way left.

If you have a rule like body
div#content p { color: #003366; } then
for every element—as it gets rendered
to the page—it'll first ask if it's a
paragraph element. If it is, it'll
work its way up the DOM and ask if
it's a div with an ID of content. If
it finds what it's looking for, it'll
continue its way up the DOM until it
reaches the body.

By working right to left, the browser
can determine whether a rule applies
to this particular element that it is
trying to paint to the viewport much
faster. To determine which rule is
more or less performant, you need to
figure out how many nodes need to be
evaluated to determine whether a style
can be applied to an element.

Google Page Speed - what do these messages mean?

First off, I have never used Page Speed, but the message is not that cryptic if you take a second to read it.

div#menu h3.soon small

Tag key with 2 descendant selectors and ID overly qualified with
tag and Class overly qualified with
tag

Tag key with 2 descendant selectors: How many small tags do you have that are not contained in another tag with class soon? None? The CSS nesting would be totally unnecessary in this case.

ID overly qualified with tag: #menu does not need to be prepended with div.
You most likely don't have any other tags in your markup with id menu (you shouldn't, its an ID!), so prepending menu with div in redundant.

Class overly qualified with tag: .soon does not need to be prepended with h3.
You most likely don't have any other tag in your markup with class soon other than h3 tags, so prepending .soon with h3 is unnecessary.

The other messages follow similarly.

-Stephen

Optimize css vs Google page speed is messing with me

Google's page speed says that specifying 2 descendants is inefficient, which may be true, but I doubt it'll make any difference on the end-user's experience. On the other hand, sometimes you have to use this way to do what you want. Other times, it's a matter of making the CSS easier to read and maintain.

Ultimately it's your CSS, so do what you want. I don't think that micro-optimization will matter.

See also: this question

What happened to the Use efficient CSS selectors rule?

In Feb 2011, Webkit core developer Antti Koivisto made several improvements to CSS selector performance in Webkit.

Antti Koivisto taught the CSS Style Selector to skip over sibling selectors and faster sorting, which bring some minor improvements, after which he landed two more awesome patches: one which enables ancestor identifier filtering for tree building, halving the remaining time in style matching over a typical page load, and a fast path for simple selectors that speed up matching up another 50% on some websites.

CSS Selector Performance has changed! (For the better) by Nicole Sullivan runs through these improvements in greater detail. In summary -

According to Antti, direct and indirect adjacent combinators can still be slow, however, ancestor filters and rule hashes can lower the impact as those selectors will only rarely be matched. He also says that there is still a lot of room for webkit to optimize pseudo classes and elements, but regardless they are much faster than trying to do the same thing with JavaScript and DOM manipulations. In fact, though there is still room for improvement, he says:

“Used in moderation pretty much everything will perform just fine from the style matching perspective.”

While browsers are much faster at matching CSS selectors, it's worth reiterating that CSS selectors should still be optimised (eg. kept as 'flat' as possible) to reduce file sizes and avoid specificity issues.

Which CSS selectors or rules can significantly affect front-end layout / rendering performance in the real world?

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:

.class1 {
/*make elements with "class1" look fancy*/
}

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.

.class1.class2 {
/*make elements with both "class1" and "class2" look extra fancy*/
}

Our example "basic engine" would go and revisit each element in DOM looking for both classes. A cleverer engine will compare n('class1') and n('class2') where n(str) is number of elements in DOM with the class str, and takes whichever is minimum; suppose that's class1, then passes on all elements with class1 looking for elements that have class2 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 or anchors (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 other divs 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):

                                                                        A      B      C
1500 class selectors (.classname) 35ms 100ms 35ms
1500 class selectors, more specific (div.classname) 36ms 110ms 37ms
1500 class selectors, even more specific (div div.classname) 40ms 115ms 40ms
1500 id selectors (#id) 35ms 99ms 35ms
1500 id selectors, more specific (div#id) 35ms 105ms 38ms
1500 id selectors, even more specific (div div#id) 40ms 110ms 39ms
1500 class selectors, with attribute (.class[title="ttl"]) 45ms 400ms 2000ms
1500 class selectors, more complex attribute (.class[title~="ttl"]) 45ms 1050ms 2200ms


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 a title and is nested within a div 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.

Identify link before certain text in Selenium IDE

Can you give a try with the below xpath:

//span[contains(text(),'add People by Role')]/preceeding-sibling::img



Related Topics



Leave a reply



Submit