A Shocking Truth about CSS
February 26, 2010
In which our heroes learn to their surprise that a fundamental assumption is wrong.
Alex M: omg
Alex M: I just learned something incredible about how css selectors are applied
Alex K: really
Alex K: what what
Alex M: yes!
Alex M: it’s changed my world
Alex M: you probably already know it
Alex M: it goes right to left
Alex M: for example: div div div div p {}
Alex M: first all p’s are gathered
Alex M: each p is analyzed for a div parent
Alex M: then the matched are again analyzed for the next left selector
Alex M: CRAZY!!
Alex M: did you know that!??!
Alex M: that is why the rightmost selector is called the key selector
Alex M: because it’s the most important key
Alex M: another example: #dogs div ul li {list-style:none}
Alex M: 1) all LIs on the page are gathered
Alex M: 2) All LIs are analyzed for a ul parent
Alex M: 3) those that matched are analyzed for a div parent
Alex M: 4) those that matched are analyzed for a #dogs parent
Alex M: then the style is applied
Alex M: This blows my mind
Alex M: changes my world
Alex K: woah
Alex K: that blows my mind too
Alex K: i had no idea
Alex K: that changes my whole set of assumptions
Alex K: doesn’t that mean that we should strive for as much specificity at the key selector level to speed up CSS processing?
Alex K: wow
Alex M: yes
Alex M: precisely!!!!
Alex M: which makes me think that manipulating LIs need to change
Alex M: whenever I manipulate LIs, for example, to be inline, I refer to them like “#inlineMenu li”
Alex M: instead each LI, for performance, should instead have .inlineMenu
Alex M: or #inlineMenu .menuItem
Alex M: something like that
Alex M: so that each .menuItem’s are gathered
Alex K: yeah
Alex K: that’s a really good point
Alex K: though that adds a ton of unnecessary DOM elements
Alex K: arg
Alex K: has anyone done speed measurement on CSS implementations?
Alex M: no unnecessary dom elements but additional classes
Alex K: sorry, that’s what i meant
Alex M: this is the article that rocked my world
Alex M: he wrote the even faster web sites book
Alex M: and sometimes
Alex M: websites go crazy with css rules
Alex M: he reported in his blog
Alex M: that like facebook uses 2800 css rules
Alex M: for 1900 dom nodes!
Alex M: so in css 3, the worst thing you can do it #menuItem ul *
Alex M: because * gathers ALL elements!
Alex M: holy schnikes!
Alex K: i’m gonna read that
Alex K: wow
Alex K: crazy
Alex K: is this a CSS 3 change, or has it always been like that
Alex M: actually I think it’s been around
Alex K: so facebook uses 2800 css classes to address this problem?
Alex M: no no
Alex M: that’s a side note
Alex M: that’s a “why the hell do you have so many styles, facebook”
Alex M: that 1.5 css rules per DOM node
Alex M: it’d be bad if it were 1 css rule per dom node
Alex M: but 1.5 is ridiculous
Alex K: yeah
Alex K: though it might be to address that
Alex K: that is shocking
Alex K: and worrying
Alex M: google uses like 90 styles for 500 dom nodes
Alex K: i’m not sure i know how to apply this to writing CSS
Alex M: er…90 rules
Alex K: like how do you manage it
Alex K: where do you cut off?
Alex M: EFFICIENCY!
Alex M: it makes me really excited
Alex M: I need to redo the redo on the yoga website
Alex K: i guess in general, you want to avoid key selectors that are just elements without classes
Alex K: yeah
Alex K: beyond that, it’s probably too hard to manage properly?
Alex M: yeah and avoid any superfluous styles
Alex M: css is always manageable
Alex M: it’s not a beast
Alex M: it’s a domesticated companion
Alex M: so no ul#menuItem
Alex M: the ul in that case is superfluous
Alex M: since IDs are unique
Alex M: or are suppose to be unique
Alex M: best css practices with good semantic markup = an amazing site
Alex M: that is how we roll
Alex M: css is like a dog companion
Alex M: and html is like a more different dog companion
Alex M: javascript is like a cat
Alex M: it forces itself upon the dogs and does whatever it wants
Alex K: hahaha
Alex K: you should write a tech blog post about this!
Alex K: just a brief one saying how it totally changed your world view and link to the article
Alex K: brb
Alex K: i’m still trying to get my head around it
Alex K: we should write up a set of rules or something
Alex K: you seem to have a sense of what the implications are
Alex M: exactly
Alex K: and i don’t think i really do
Alex K: wow
Alex K: not every day your world is thrown in disarray
Alex M: here’s the table of CSS rules to DOM elements
Alex K: wow, IE8 is FAST
Alex K: huh
Alex K: that makes it sound like it may not be worth huge optimization?
Alex M: no, not really
Alex M: I’m a purist though
Alex M: so this makes my world
You should watch this video: http://www.youtube.com/watch?v=a2_6bGNZ7bA (Faster HTML and CSS: Layout Engine Internals for Web Developers). It’s a great introduction to how browsers use CSS selectors and how they do the rendering of web pages.
[...] full post on Hacker News If you enjoyed this article, please consider sharing it! Tagged with: ABOUT • [...]
Awesome article. Gotta admit I love the conversational style. Nice job.
While it’s great to be aware that this is the case, I think Steve’s final conclusion should be noted:
“For most web sites, the possible performance gains from optimizing CSS selectors will be small, and are not worth the costs. ”
http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/
Yes, selectors are matched from right to left. But it works slightly differently than you described it here. Browsers DO NOT find DOM nodes for CSS selectors, it’s vice versa – for each DOM node browser finds matching selectors – and that explains why matching works from right to left.
More on this:
Writing Efficient CSS for use in the Mozilla UI
https://developer.mozilla.org/en/Writing_Efficient_CSS
Faster HTML and CSS: Layout Engine Internals for Web Developers
http://www.youtube.com/watch?v=a2_6bGNZ7bA
Hey everyone,
Thanks for the comments! It’s very cool (and unexpected) to see this picked up.
Learning that CSS is process from right-to-left was a fun surprise — all the astonishment of overturning a fundamental assumption without any of the pain of having to make changes. (Much as John points out.)
Brad: thanks
it worked out nicely. I wanted to write a blog post, so I just copied (nearly) word-for-word the gChat conversation I’d just had with my husband (M).
Steve and Bruno: thanks for the links. The Mozilla site is very enlightening and concretely useful. Do either of you know if other browsers handle CSS processing in a similar fashion as described in the Mozilla link?
I haven’t watched the video yet, but clearly we should.
Cheers,
Alex K
[...] No mention of fractions: Web Standards for E-books Why fractions matter: Is Adobe Hindering eBooks? A Shocking Truth about CSS Getting New Users to Stick: Deconstructing how the best sites convert visitors to customers (Part 1 [...]
[...] A CSS Revelation Just a reminder: CSS selectors are applied right to left. Two developers share a moment of revelation. See also the original post by Steve Souders: Simplifying CSS Selectors. [...]
When I started researching performance of CSS selectors, I had heard horror stories of how they were responsible for bringing web pages to a crawl. As I dug into those specific test cases, it turned out it was a combination of bad CSS and bad JavaScript.
As I focused on pure CSS selector performance, I found that for most sites this isn’t a high priority to fix. But certainly for some sites it is a problem. I’ll plug Page Speed here ( http://code.google.com/speed/page-speed/ ) because it has a rule that checks for inefficient CSS selectors and lists the worst offenders.
Thanks for evangelizing this.
You may have a look at the “match()” method in NWMatcher selector engine, it does exactly that, compiles CSS 3 selectors to pure “bottom-up” ad-hoc resolver functions. This is what makes so incredibly fast and specs compliant.
I have setup a comparison between “internal” CSS selectors and frameworks/libraries selector engines here:
http://dl.dropbox.com/u/598365/css3-compat/css3-compat.html
the test was to measure consistency between the various implementation and frameworks actual browsers support and bug fixing capabilities. It looks like too much talk about speed instead of consistency.
@steve, selectors are used in several ways, there are situation where the “match()” or equivalent method is going to be called several times per seconds as in event delegation, so selectors engines performance is key to faster UI interactions, though some kb more to download
Thank you for the good article.