So I've recently been doing a lot of work with Concrete5. I noticed, however, that the default theme has many CSS rules which are defined like so:
#page #central #sidebar p{line-height:24px}
Since "sidebar" is an ID there should only be one "sidebar" on the entire page (assuming that it validates, which I'm taking care it does). Therefore if #sidebar
is in #page #central
, it should always be in #page #central
. No matter what. On every page.
By this logic, the following rule does the exact same thing:
#sidebar p{line-height:24px}
Testing this, sure enough, it worked. So my question is- which would have better performance? Is there a speed-related reason that the Concrete5 team went with the longer specification, or was it merely to help future developers locate the #sidebar
div? I can see arguments for it being faster in either case.
If case 1 is faster (#page #central #sidebar
):
If the browser uses a breadth-first-search algorithm to locate the proper DOM element then finding #sidebar
would involve searching the second tier of EVERY DOM element that had children before it reached the third tier, at which point it would still have several elements it looks at before finding #sidebar
. By specifying the elements in this way the breadth-first-search would recognize #page
and know that it only needs to continue searching within this element, rather than continuing with the entire DOM.
If case 2 is faster (#sidebar
):
If the browser searches the entire document in the order it's written, rather than treating the DOM like a tree, then it would be performing a single linear search rather than three linear searches. In fact, even in the best-case scenario where it's smart enough to recognize the start and end points of the previously found DOM element (essentially a depth-first-search), it would still have to read just as many lines of code in a linear search - first it would read until it found #page
, then it would start reading from the start of #page
until it found #center
, then it would read from the start of #center
until it found #sidebar
. The only difference then would be the slight amount of overhead involved in switching from one search to another
If there are two or more CSS rules that point to the same element, the selector with the highest specificity value will "win", and its style declaration will be applied to that HTML element.
The important thing to remember is that using an ID in a selector is very specific, and should be used sparingly. A few words on specificity: Generally speaking, one should use the lowest possible specificity selector that makes the correct selection: If you're targeting all <a> elements, then it makes sense to use a .
Inline styles added to an element (e.g., style="font-weight: bold;" ) always overwrite any normal styles in author stylesheets, and therefore, can be thought of as having the highest specificity.
Short story: the more of anything you use, the slower it is to parse.
An ID is always unique, so you should only ever use one; but even with classes, specifying any other elements or criteria is always going to be slower.
http://css-tricks.com/efficiently-rendering-css/
That article goes far more in depth into exactly what you are asking about.
AFAIK there is no feasible way of testing the speed of browsers CSS matching algorithm, and the differences between #page #central #sidebar
and #sidebar
as far as speed is concerned is so negligible that it's not worth worrying about.
What is worth worrying about is the difference in specificity.
Sometimes it's worth adding an extra id/class/element to a selector to make sure the style doesn't get overwritten by mistake with a simple selector later on in the cascade.
#page #central #sidebar p
has a specificity of 3-0-1, while #sidebar p
has a specificity of 1-0-1, which means that #page #central #sidebar p
will take precedence.
Additionally, you mentioned:
...if #sidebar is in #page #central, it should always be in #page #central. No matter what. On every page.
This is very much not the case, and is important to understand why. Just because an id
is unique, does not mean that it must follow the exact same page structure on every page.
For example: a popular content management system (Drupal) allows the developer to specify rules for the placement of blocks on differing areas of different pages. I may want the #search-block
to be in the #header
on the homepage and then in the #sidebar
in all other pages. using a more specific selector would allow me to give the #search-block
different styles depending on what its parent containers are.
Performance issues aside, these don't always translate to the same thing.
#header {
background: blue;
}
#home #header {
background: red;
}
This is a perfectly valid use of the cascade to make one page appear different to another. I use this pattern all the time, usually because I assign class
or id
to my body
element, as a hook for CSS and JavaScript.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With