Recently I came across the post by Matt Wilcox Called CSS Lint is Harmful Speaking of the Useful Free Tool CSS Lint . The suggestion "Do not use identifiers in selectors" seems to have the most offended Matt, but I was surprised that many commentators also mentioned this as being a reason to avoid CSS Lint. That surprised me because intelligent people said preferred classes to identity cards for a moment now. The article was light on why this suggestion might be bad, but it boils down to:
Performance: IDs are "the fastest way a browser can select a given item"
If they are already in the markup, it is best to use them for CSS
I've used identifiers as forever … waddya means I should not use them !?
Contents
Performance #
It's a common belief that ID selectors are the fastest, but this comes with a big caveat: IDs are the fastest CSS selector only if they are the key selector. What is it? Well, while you probably read the selectors from left to right, read them from right to left .
#Home to {…}
We usually read this selector as finding the element with id = "home", then apply these styles to each it contains. That should be super fast, right? After all, there should be only one id = "home" on the page. However, browsers read differently: find each element, then check if its parent element is id = "home", and otherwise continue to check for parent elements until you find them or reach them . It's much less powerful than our mental model.
As you have deduced, the key selector is the rightmost key selector (a in #home a {…}). So, what kind of performance difference does it really make? I used CSS Test Creator from Steve Souders and I did three tests that I recorded locally. Each test has 1,000 items selected for the use of identifiers, classes or individual identifiers with selectors, e.g. for ID's:
# id0001 {…}
# id0002 {…}
# id0003 {…}
…
# id1000 {…}
I then reloaded the pages several times to get average page loading times (in Chrome 12, except for the initial loading of the page)
Selector performance for 1000 elements (in ms)
# id …
.class…
# id … a
90.3
91.5
104
94
93
115
91
92
101
90
91
100
90
91
100
88
92
106
89
90
102
So for 1000 rules, IDs are faster by one millisecond than classes as a key selector. Yes, the difference in performance between classes and IDs is not relevant . The most common scenario of using an ID for 'namespace' an element (where the element is the key selector) is actually slower than the use of a class, but the difference of 13 milliseconds observed is not relevant. This is also true for the few extra bytes that it takes to add a class to something that already has an ID, eg. changing
Note that this does not mean that all selectors are equal – the universal selector * {…} and some CSS 3 selectors have relatively poor performance when used as a key selector.
Results from Measuring the performance of the CSS selection script on bitbucket.org (in Chrome 12)
% (100% is the baseline)
CSS selector
~ 100%
.class, .class: not (a), .class [a] #id, .class: nth-child (odd), element, no style
~ 870%
[class^=”a”] [title=”a”]
~ 1020%
[a] [a=”b”]
However, if you mainly use one or two selectors (elements and / or classes), the use of CSS 3 selectors where appropriate is no problem. Differences from selectors are small compared to others, and you can further improve performance orders by optimizing images and reducing HTTP requests.
IDs are brittle #
In addition to style hooks, IDs are used as fragment identifiers (a href that ends with #anchor leading you to id = "anchor"), and getElementById of JavaScript. If you add IDs for these other reasons, why not reuse them for style? The problem is that this makes your code fragile – you have configured dependencies between CSS and your JavaScript and / or a fragment identifier. By using classes, you can decide to change to a (new) naming scheme at any time, and all you need to worry about is changing the name of your CSS and HTML.
There are also very few instances where ID-based styles will ever be reused. An example uses #search for the search area of your site. You can decide later to add a search box at the top and bottom of your search results. Even though #search is unique in this project, you may want to copy and paste CSS quickly into a future project that also has a search box in the footer. Even for a complex and unique group of styles, you can usually break them down into several reusable CSS snippets. Using classes on IDs prevents these potential problems.
In addition, unlike IDs, there is no restriction on multiple classes, either by using the same class more than once on the page, or by using more than one class. class on an element. Browsers will continue to style the credentials, even if you duplicate one by mistake, but if you venture outside of a valid HTML code, you may encounter problems.
Wars of specificity! #
The use of an ID on a class also increases the specificity up to Dark Sidious in the guide to the specificity of CSS by Andy Clarke on CSS specificity . Even if you do not think it's a big problem, it quickly leads to a complete selection battle. This problem worsens as CSS grows and more people get involved, leading to madness-specific selectors like .entry #content_main div.post> at {…}. This rule could probably be rewritten at least under .entry .post> a {…}, or maybe .post> a {…}, but changing it to .block-link {…} would still be better. My general rule is three max CSS selectors – no more than that and it's usually a sign of problems (specificity).
"Tricky CSS inheritance question – challenge accepted" by the awes Mathias Bynens (@mathias)
But but but … I used identifiers like foreva! #
The style with IDs and classes is one of the first things we learned about CSS, so it can be difficult to hear "do not use ID in CSS selectors. However, this industry is constantly evolving. Sometimes we need to re-evaluate what works and what does not work, rather than staying true to what has served us well. We are experiencing a massive rebirth with HTML5, CSS3, amazing JavaScript performance and fast browser launches, so it's the right time to do it. This is a small change, like that of to for anchor links / fragment identifiers. However, it is important to consider the reasons rationally and decide whether they are valid, rather than rejecting them from the outset.
The roles of ARIA's landmark #
By focusing on identifiers and classes, I have completely neglected another way of selecting HTML5 structural elements, such as a page
Conclusion #
It seems to me that there are no compelling reasons to use IDs in selectors for the CSS style ¹ because CSS classes can do all that that IDs can do. I hope you will agree that there are good reasons not to do it. Think about it the next time you start a personal project or redraw your own site, and try to add a class (or an ARIA landmark role) for the style. Save IDs for fragment identifiers or JavaScript hooks.
If you have comments or comments, contact me via Twitter (@boblet) or Google+ (Oli Studholme) .
¹ with the exception of the user style on a domain ID, and possibly the namespace attempt on widgets, CMS plugins and others
Modifications #
2011-07-20 Har! So, as soon as I publish this, I find that Dave Gregory wrote the same post on screwlewse.com almost exactly a year ago. I am behind the time.
2011-07-20 Some small adjustments, plus confronting my passive-aggressive-ism by adding a link to the original article of Matt Wilcox (thanks to John -David Dalton )
2011-07-27 Added information about using the ARIA benchmark roles as selectors after reading some good articles on the subject. It reminds me of an old article that I have to update …
2011-09-24 Addition of the image Challenge accepted "to the section Specificity of the wars! . ! important all things! :RE
2012-01-19 Finally credited @mathias for the "Challenge accepted" imgur