{"id":6386,"date":"2010-05-24T06:13:10","date_gmt":"2010-05-24T13:13:10","guid":{"rendered":"http:\/\/css-tricks.com\/?p=6386"},"modified":"2019-09-26T10:32:44","modified_gmt":"2019-09-26T17:32:44","slug":"efficiently-rendering-css","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/efficiently-rendering-css\/","title":{"rendered":"Efficiently Rendering\u00a0CSS"},"content":{"rendered":"
I admittedly don’t think about this idea very often… how efficient is the CSS that we write, in terms of how quickly the browser can render it? <\/strong><\/p>\n This is definitely something that browser vendors care about (the faster pages load the happier people are using their products). Mozilla has an article about best practices<\/a>. Google is also always on a crusade to make the web faster. They also have an article about it<\/a>. <\/p>\n Let’s cover some of the big ideas they present, and then discuss the practicalities of it all.<\/p>\n <\/p>\n One of the important things to understand about how browsers read your CSS selectors, is that they read them from right to left<\/strong>. That means that in the selector ul > li a[title=\"home\"]<\/tt> the first thing thing interpreted is a[title=\"home\"]<\/tt>. This first part is also referred to as the “key selector” in that ultimately, it is the element being selected.<\/p>\n There are four kinds of key selectors: ID, class, tag, and universal. It is that same order in how efficient they are. <\/p>\n When we combine this right-to-left idea, and the key selector idea, we can see that this selector isn’t very efficient:<\/p>\n Even though that feels weirdly counter-intuitive… Since ID’s are so efficient we would think the browser could just find that ID quickly and then find the li children quickly. But in reality, the relatively slow li tag selector is run first. <\/p>\n Never do this:<\/p>\n ID’s are unique, so they don’t need a tag name to go along with it. Doing so makes the selector less efficient.<\/p>\n Don’t do it with class names either, if you can avoid it. Classes aren’t unique, so theoretically you could have a class name do something that could be useful on multiple different elements. And if you wanted to have that styling be different depending on the element, you might need to tag-qualify (e.g. li.first<\/tt>), but that’s pretty rare, so in general, don’t.<\/p>\n David Hyatt:<\/p>\n The descendant selector is the most expensive selector in CSS. It is dreadfully expensive — especially if the selector is in the Tag or Universal Category.<\/p><\/blockquote>\n In other words, a selector like this is an efficiency disaster:<\/p>\n I’m not sure if there is much we can learn from this, because if you have a bunch of selectors in your CSS that don’t match anything, that’s, uhm, pretty weird. But it’s interesting to note, that in the right-to-left interpretation of a selector, as soon as it fails a match, it stops trying, and thus expends less energy than if it needed to keep interpreting.<\/p>\n Consider this:<\/p>\n Font-family<\/tt> cascades, so you may not need a selector that is that specific to begin with (if all you are doing is changing the font). This may be just as effective, and far more efficient:<\/p>\n Kind of sad news from David Hyatt:<\/p>\n The sad truth about CSS3 selectors is that they really shouldn\u2019t be used at all if you care about page performance. <\/p><\/blockquote>\nRight to Left<\/h3>\n
ID’s are the most efficient, Universal are the least<\/h3>\n
#main-navigation { } \/* ID (Fastest) *\/\r\nbody.home #page-wrap { } \/* ID *\/\r\n.main-navigation { } \/* Class *\/\r\nul li a.current { } \/* Class *\r\nul { } \/* Tag *\/\r\nul li a { } \/* Tag *\/\r\n* { } \/* Universal (Slowest) *\/\r\n#content [title='home'] \/* Universal *\/<\/code><\/pre>\n
#main-nav > li { } \/* Slower than it might seem *\/<\/code><\/pre>\n
Don’t tag-qualify<\/h3>\n
ul#main-navigation { }<\/code><\/pre>\n
Descendant selectors are the worst<\/h3>\n
html body ul li a { }<\/code><\/pre>\n
A selector that fails is more efficient than that same selector matching<\/h3>\n
Consider why you are writing the selector<\/h3>\n
#main-navigation li a { font-family: Georgia, Serif; }<\/code><\/pre>\n
#main-navigation { font-family: Georgia, Serif; }<\/code><\/pre>\n
CSS3 and Efficiency<\/h3>\n