6 ms·
Writing efficient CSS selectors
- etrinh 14y agoA 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.
- csswizardry 14y agoHey, article author here :) > A lot of great information here. Thanks! > …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-designers-and-front-end-developers/#section:css-and-performance http://csswizardry.com/2013/01/front-end-performance-for-web... </plug> Cheers! H
- ufukbay 14y agoIs 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?
- csswizardry 14y agoQualifying 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 I have written a lot about CSS selectors: http://csswizardry.com/2012/05/keep-your-css-selectors-short/ http://csswizardry.com/2012/05/keep-your-css-selectors-short... http://csswizardry.com/2012/07/quasi-qualified-css-selectors/ http://csswizardry.com/2012/07/quasi-qualified-css-selectors... http://csswizardry.com/2012/07/shoot-to-kill-css-selector-intent/ http://csswizardry.com/2012/07/shoot-to-kill-css-selector-in... H
- ufukbay 14y agoThanks for the reply and the links, I will check them out. :)
- bung 14y agoMaybe 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?
- janzer 14y agoNote that this article is from 2011. 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]
- csswizardry 14y agoYep, I should probably add something to the article about this; browsers now are so fast that tests show little to no difference :)
- youngtaff 14y agoBrowser makers have also done a fair bit of work to speed up the selectors - I'll see if I can find the article
- nemetroid 14y agoThe 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: http://jsfiddle.net/zsjrN/ http://jsfiddle.net/zsjrN/ Only the first paragraph should be red.
- aptwebapps 14y agoIds are supposed to be unique but I don't think that browsers are supposed to assume that they are.
- ams6110 14y ago
- ericcholis 14y agoIt's worth noting that this is from 2011. Here's some more discussion on the topic: https://developers.google.com/speed/docs/best-practices/rendering https://developers.google.com/speed/docs/best-practices/rend... https://developer.mozilla.org/en-US/docs/CSS/Writing_Efficient_CSS https://developer.mozilla.org/en-US/docs/CSS/Writing_Efficie...
- ohwp 14y agoI think it's also good practice to check if you can reduce your DOM. <ul id="social"> <li><a href="#" class="social-link twitter">Twitter</a></li> <li><a href="#" class="social-link facebook">Facebook</a></li> <li><a href="#" class="social-link dribble">Dribbble</a></li> <li><a href="#" class="social-link gplus">Google+</a></li> </ul> could be written as: <a href="#" class="social-link twitter">Twitter</a> <a href="#" class="social-link facebook">Facebook</a> <a href="#" class="social-link dribble">Dribbble</a> <a href="#" class="social-link gplus">Google+</a> since you already have the social-link classes attached to it. Another example. This: <div id="header"><h1>header</h1></div> could be written as: <h1>header</h1> since you should have only one H1 on your page.
- blowski 14y agoIn HTML5, it's fine to have multiple `h1` tags on the page, though you can only have 1 in each `section`.
- ohwp 14y agoI know it's fine, but I think you shouldn't because of SEO. But to keep this on topic: my point is: a lot of time you can reduce your DOM.
- blowski 14y agoEven 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. Matt Cutts talking about this: http://www.youtube.com/watch?feature=player_embedded&v=GIn5qJKU8VM# http://www.youtube.com/watch?feature=player_embedded&v=G...!
- adlpz 14y agoAs 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.
- 14y ago
- batiste 14y agoPlease read this, CSS Selector Performance has changed! (For the better) http://calendar.perfplanet.com/2011/css-selector-performance-has-changed-for-the-better/?x=95&y=1 http://calendar.perfplanet.com/2011/css-selector-performance...
- lince 14y agoDo really selectors work that way? I always though that if I had: #social a The browser first get the social, then the "a" tag and analyze and store it in some DOM tree style information.
- ams6110 14y agoI 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. From http://snook.ca/archives/html_and_css/css-parent-selectors http://snook.ca/archives/html_and_css/css-parent-selectors 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.
- podperson 14y agoThat 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().
- youngtaff 14y agoYes, selectors really match from right to left Boris Zbarsky gives a good explanation of why here: http://stackoverflow.com/questions/5797014/why-do-browsers-match-css-selectors-from-right-to-left http://stackoverflow.com/questions/5797014/why-do-browsers-m...
- smagch 14y agoFor more resources about CSS optimization, Google https://developers.google.com/speed/docs/best-practices/rendering https://developers.google.com/speed/docs/best-practices/rend... Github http://news.ycombinator.com/item?id=4890384 http://news.ycombinator.com/item?id=4890384
- talmand 14y agoI 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.
- bpatrianakos 14y agoThe 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. [1]https://speakerdeck.com/csswizardry/breaking-good-habits-1 https://speakerdeck.com/csswizardry/breaking-good-habits-1
- pulledpork 14y agoI'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.
- Schlaefer 14y agoIf 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. [1] http://fortawesome.github.com/Font-Awesome/ http://fortawesome.github.com/Font-Awesome/
- deleted 14y ago[deleted]
- mcgwiz 14y agoThese 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 now very precise: body { color: black; } .menu > .-item { color: orange; } 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.)