Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quicker of two CSS rules: with/without multiple IDs specified

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

like image 591
stevendesu Avatar asked Jan 24 '11 05:01

stevendesu


People also ask

What happens when multiple conflicting CSS rules match the same element?

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.

Is ID selector highly specific?

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 .

Which CSS rule has the most specificity?

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.


3 Answers

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.

like image 138
scragz Avatar answered Oct 14 '22 09:10

scragz


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.

like image 43
zzzzBov Avatar answered Oct 14 '22 09:10

zzzzBov


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.

like image 36
alex Avatar answered Oct 14 '22 10:10

alex