Trying his tests on firefox 20 beta, shows no difference between id and class selectors (the article says there was minimal difference in ff6), also no difference between between the type and "heavily overqualified descendant" selectors (article reports a large difference) and the latter pair are approximately twice faster than the former (the article seems to report they were up to 40 times slower).
So beware that browser technology has progressed since the time of this writing. Of course once again you should be checking the behavior of your site with the browsers your users are actually using.
[Edit: originally confused the two pairs of tests in my browser tabs, the slow tests in ff6 are actually the faster tests in ff20]
The only reason id selectors would be faster (that I can think of) is that ids are supposed to be unique, so the matching can stop after finding the first element with an id. However, none of the browsers I tested this in actually did so. Here's an example:
The only time I've known that the uniqueness of ids to be in play is either as a target of an anchor or to be used in Javascript. As far as I know, in those cases only the first element with that id will be involved.
Removing the CSS from your example, and then using Javascript to change the color you see that only the first one is altered.
So, in terms of CSS, it doesn't really matter. Well, I don't know about performance issues with it though. But for Javascript it matters a great deal. As for HTML, it only really matters in that it's supposed to be unique for anchor targets, which would be one reason it doesn't validate.
Browsers give a great deal of leeway when it comes to HTML and CSS, because so many people and editors do not follow the spec. Of course, you could argue that no one follows the spec because the browsers don't really enforce it. I've been constantly amazed over the years seeing various examples of HTML soup that should not render in any recognizable form that somehow renders in the browser.
There are a lot of "supposed to" rules in HTML and CSS that many people violate in practice, and browsers for the most part try to accomodate that if they can. Not surprised to hear that non-unique ids are permitted.
In practice, since so many web developers violate the rule about ids being unique, I think browser devs are forced to make the ID map into a multi-map, which makes it exactly the same as the class map.
A lot of great information here. I always knew that overqualifying selectors was bad, but it was always from a "clean code" point of view and not so much from a performance standpoint. Even more reason to avoid them now.
Although this is very interesting information, anyone reading this article should pay careful attention to the ending headline, "Is all this really necessary?" Odds are, unless you've produced some kind of CSS monstrosity, your CSS isn't the bottleneck in your website performance. Min and concat your Javascript, use appcache, local storage, etc. before prioritizing CSS performance.
> …unless you've produced some kind of CSS monstrosity, your CSS isn't the bottleneck in your website performance.
You’re definitely right insofar as selector efficiency should be last on your list of things-to-make-my-site-faster. CSS as a whole, however, is a pretty significant performance concern; I wrote a little more about that here: http://csswizardry.com/2013/01/front-end-performance-for-web... </plug>
Maybe a dumb question, but if you are making one of these larger sites, and you add classes to everything because there are "100s of <a> tags" ... does all the added bytes to the HTML matter less than the time it takes to parse CSS? or does it not make any difference, I guess we're talking about milliseconds here? Would some people choose to push it onto the client and reduce their bandwidth?
Is there a performance difference between using "div#container" and "#container"? When reading the css, I find it easier to be reminded that the element with the id container is a div element, but I guess its an additional check for the browser right?
Qualifying selectors like that is always a bad idea because:
1) What if you ever need to use the selector on a different element?
2) A performance hit (though so slight it might as well not matter)
3) Increased specificity
The most important piece of this is somewhat between the lines here though I think he kind of comes out and says it at some points (I'd recommend you check out his SpeakerDeck presentation[1] which mentions this too).
CSS efficiency is a balancing act between best practices, speed, and maintainability. CSS rendering is really cheap compared to JavaScript or most other things, HTML excluded. So yeah, be aware of efficiency but don't let it come at the expense of maintainability. If you add a "non-semantic" class here or there so another developer can immediately understand what you're doing it's not going to be the end of the world and in fact is probably the right thing to do, efficiency be damned.
What I always try to do is identify patterns and use IDs and classes accordingly. So, for example, I've got an app that displays success and error messages based on input. I originally (and stupidly) gave each one its own class (i.e. '.user-signup-error' or '.save-file-error'). That wasn't going to scale. So I went back in and gave each type of design element it's own generic class. So now there are things like ".notification-box" and ".error-msg". All elements of that type will be notification-box'es and be given a default style then I'll have another class added to the same element indicating the type of message. IDs are real useful for giving JS something to hook onto but otherwise HTML5 has allowed us to now get rid of a lot of those #nav, #header, #sidebar IDs and instead just use the appropriate element name (nav, header, aside, footer, etc.) which is pretty cool.
All in all though, this is something to be aware of but not to worry too much about. Being too strict about efficiency can be just as bad as being overly inefficient.
These are always interesting articles, but rarely of practical value. Performance is only one concern of a website project. I've found that a greater risk by far is predictable modularization, a topic with much less "engineering" attention. Any decent-sized project is going to have to decompose their presentation declarations info manageable artifacts, which has the unwanted side-effect of spreading out existing selectors across multiple files. Add to this a tight project timeframe, several engineers that treat CSS as a second-rate language (as almost all that I've encountered do, worsening the more senior they are), and CSS' lack of selector-spacing (in the namespace sense), and you have a recipe for thermonuclear battles over selector specificity.
Selector and naming conventions can basically eliminate this problem. Module root elements have a class name that starts with a letter; module nested elements have a class name that starts with a dash. These are combined with the child selector to constrain their applicability.
What was once super-ambiguous, e.g.
body { color: black; }
.menu .item { color: orange; }
.menu .item .menu { color: black; }
.menu .item .menu .item { color: orange; }
/* and on */
Is it the most efficiently interpreted ruleset? No, and I don't care. It's the most efficiently manageable ruleset. (Web Components will probably obviate this.)
I think OOCSS has a strong influence on this use of multiple classes instead of your example of nesting classes (which i would have done, too).
I'm not saying I totally agree, but OOCSS promotes the idea that your styles should be decoupled from your HTML structure. This makes CSS easier to maintain.
For your first example it depends on various factors. Sometimes having the links inside a list is more efficient in terms of styling versus having a series of repeating anchors. Then again, in most cases you can just as easily wrap the anchors in a div with similar outcomes.
About this:
<div id="header"><h1>header</h1></div>
There are reasons to do this. If all your doing is simply wrapping a block element with a block element then that's likely not a good idea. You are right in that if any styling done to the div can be done to the h1 then you might as well skip using the div in the first place.
One reason to do that is for a header with a defined size that has a background image for display and the h1 is text inside that header that can be placed via positioning. Although more than likely the h1 is not a good choice for that role.
It's worth mentioning that in HTML 5.1 they are now recommending that you use headings with an appropriate rank. Not that it's wrong to have multiple H1 tags, just not recommended anymore.
Exact wording:
Sections may contain headings of any rank, but authors are strongly encouraged to use headings of the appropriate rank for the section's nesting level.
Hmmm, interesting. So that's going in the other direction to the HTML5 spec, in which you considered a header in relation to the section it's contained in, without worrying about the section's relation to the whole document. It was the browser's job to do the latter.
I will keep an eye on this. Thanks for the pointer.
The final editor's response explains the reasoning:
"Change removed advice recommending use of h1 elements as the utline algorithm has virtually no implementations and as a result use of h1 elements flattens document outlines for users who actually consume the heading semantics. While use of elements of the appropriate rank for the section's nesting level is backwards compatible"
Even then, it's fine as long as you're structuring your page sensibly. For example, on a blog index where each blog post is in a section, it's fine for each blog title to be a h1.
As I understand it, the whole "SEO mandates one h1 per site" is outdated. Search engines (read, Google) now follow HTML5 specs and, if you are doing your semantic tagging right, multiple h1 aren't a concern anymore.
I thought the same. If this is true (it finds <a> elements then looks for the id), I've been writing a lot of poor-performing selectors.
Edit: I found that it does work this way, and the reason is because browsers process content and apply CSS top to bottom as it renders, they do not first load all the content and then apply CSS rules.
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.
That bit certainly surprised me. It seems like a simple optimization to scan a selector for the most efficient parts and use that as your starting point (with ids being a no-brainer).
Obviously given the selector "div #foo a {}" (obviously a dumb selector, but...) it would be smarter to look for #foo and verify it was inside a div than get every div and search for a #foo. And by extension "div .foo a {}" (assuming .foo really is way more efficient than div, which again I find hard to believe given there's native support for getElementsByTagType).
It seems to me that the effectiveness of using classes probably stems from browsers optimizing against use cases like "OMG folks are using Dijit and hanging twelve classes off every div". There's no reason I can see why class selectors ought to be especially efficient, especially if -- say -- your markup has lots of classes and relatively few attributes (and isn't that more common these days?).
We should also probably differentiate between CSS selectors as affects page rendering and CSS selectors as affects grabbing a bag of nodes using jQuery $() or document.querySelectorAll().
I find it interesting that instead of using tags to target a list-item, it suggests putting a class on every li in the HTML. Seems rather bloating to the HMTL if you have a number of long lists.
Is using descendant selectors in that case bad enough to offset all those class attributes? I think I'd rather put a class on the ul or ol so that I can target the parents if needed and then can still easily target the li children.
I've created dozens of sites and never really noticed any CSS performance issues.
I have got orders of magnitude faster sites by combining CSS or js files, gzipping content, adding cache control headers, serving via a cdn and not serving code that's not used.
I've also really benefitted from using logical markup and CSS selectors, not those designed for "efficiency" of the computer rendering them.
If you are done with the obvious optimizations, at some point you spend half a day to gain 50 ms on the backend. And that's a good day. If you are able to achieve 25 ms on the frontend in half an hour, it's worth considering. E.g. Font Awesome [1] is very popular, but the selector performance is horrible.
Trying his tests on firefox 20 beta, shows no difference between id and class selectors (the article says there was minimal difference in ff6), also no difference between between the type and "heavily overqualified descendant" selectors (article reports a large difference) and the latter pair are approximately twice faster than the former (the article seems to report they were up to 40 times slower).
So beware that browser technology has progressed since the time of this writing. Of course once again you should be checking the behavior of your site with the browsers your users are actually using.
[Edit: originally confused the two pairs of tests in my browser tabs, the slow tests in ff6 are actually the faster tests in ff20]