Get Specific with Your CSS Styles

Notice: This is a discussion thread for comments about the SitePoint article, Get Specific with Your CSS Styles.


I really wish that things just happened in the order they appeared in the stylesheet, ignoring specificity…

[QUOTE=Stomme poes;4603113K]i

Or is Anne incorrect?[/QUOTE]

Anne is correct but the following link from Steve Souders (which I quote often) covers this issue in detail here with some interesting results. In the real world it makes negligible difference and is only in stressing the browser beyond normal limits that things take a turn for the worse.

I prefer shorter rules anyway because they are easier to manage and if there is also an incidental speed gain to be made then it’s all good but 99% of the time there will be no noticeable difference.

However it would be good to see tests on advanced css3 selectors but Im guessing again that you would need to use worst case scenarios to make any noticeable difference.

Kindof off-topic, but I didn’t know this until a recent talk by Anne van Kesteren:

When you have
<body>

<table>

<td class=“bar”>some stuff</td>
…rest of page

if you say
.bar {
styles;
}
that’s quite fast for the browser. But this
td.bar {
styles;
}
is slower. The browser works from right to left (I did not know this, I thought it walked the DOM forwards), so first it finds all .bars, then it checks to see if those .bars belong to a td.

This then takes even longer:
body table tr td.bar {
styles;
}
again because the browser first gets all .bars, then all td.bars, then all tr td.bars, then all table tr td.bars, then all body table tr td.bars.

Not that it’s a noticeable penalty in any browser. But I thought it was pretty interesting. You’d think CSS would be able to benefit from the pre-scanned DOM like JS?
Or am I missing something else?

Or is Anne incorrect?

HI Paul
Thanks for the overview. One puzzlement for me is your statement:
“Note that [id=“foo”] is not equivalent to #foo – you can see there’s a significant difference in their levels of specificity.”
This may make sense for some others, but it is not immediately evident to me that there is a ‘significant difference’- could you point me at a reference to clear this up for me? Cheers.

Hi,

I’ll try :slight_smile:

[id=“foo”] relates to attribute selectors which carry less weight than styles set via ID and as shown in the table in the article. It has nothing to do really with it being an ID but the fact that it is an attribute selector - e.g. input[type="text]{}

Working from left to right the highest specificity is at the left and the lowest specificity at the right:

Inline styles | ID | Classes, Attribute selectors and Pseudo classes | Element types and pseudo elements.

Calculating Specificity

Here's a simplified description of the process by which the  specificity of the selectors of two or more declarations is compared:
  1. If one declaration is from a style attribute, rather than a rule with a selector (an inline style), it has the highest specificity. If none of the declarations are inline, proceed to step two.
  2. Count the ID selectors. The declaration with the highest count has the highest specificity. If two or more have the same number of ID selectors, or they all have zero ID selectors, proceed to step three.
  3. Count the class selectors (for example, .test), [URL=“http://reference.sitepoint.com/css/attributeselector”]attribute selectors (for example, [type=“submit”]), and [URL=“http://reference.sitepoint.com/css/pseudoclasses”]pseudo-classes (for example, :hover). The declaration with the highest total has the highest specificity. If two or more have the same total, or they all have totals of zero, proceed to step four.
  4. Count the element type selectors (for example [URL=“http://reference.sitepoint.com/html/div”]div) and [URL=“http://reference.sitepoint.com/css/pseudoelements”]pseudo-elements (for example, :first-letter). The declaration with the highes

So as an example to clarify you will see from the following that the background of the element is blue and not red.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style type="text/css">
#test {background:blue}
p[id="test"] {background:red}
</style>
</head>
<body>
<p id="test"> This will be blue because the ID has more weight</p>
</body>
</html>


Is that what you meant?

I think you’ve got a comma in the wrong place. “If one declaration is from a style attribute, rather than a rule with a selector (an inline style),” should be “If one declaration is from a style attribute, rather than a rule with a selector, (an inline style)”.

The way you’ve written it makes it look as though a rule with a selector is called an inline style, not the other way round…

Great article Paul, feel like I fully understand this concept now.

For anyone wanting some more info on CSS specificty you should also read although it misses the important part of inline styles

http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

@Php_penguin Why do you wish that? If you have to include multiple CSS files it would be horrible having to worry about if your styles were being overwritten.

  1. Why have you taken tabular data and saved it as an inaccessible image file, instead of a properly marked up table?

  2. When styles of equal specificity are defined in different places (eg multiple stylesheets and css called via @import), is it still the last rule in the last referenced stylesheet that takes precedence?

  1. When styles of equal specificity are defined in different places (eg multiple stylesheets and css called via @import), is it still the last rule in the last referenced stylesheet that takes precedence?

Yes :slight_smile:

It makes no difference where styles come from as they are inserted into the cascade order at the point they were called from (remembering that the @import rules in a style sheet must precede all rule sets anyway.).

As all styles are called into the page (by link or import) then they occupy the position in the order that they were called from.

  1. Why have you taken tabular data and saved it as an inaccessible image file, instead of a properly marked up table?

You’ll have to ask the editor :slight_smile:

Keep in mind that @import rules require extra HTTP requests to the server. So if you’re having web site performance issues, that can be a source.

That was kind of off-topic.

Good article, I’m a big fan of putting an ID and class on the body element. It keeps HTML really clean, and you can also style the html and body elements for page width, rather than using a “container” or “wrap” div… big fan.

What I was thinking is that you could have the situation where you had two linked stylesheets, and each of them had @import rules at the top.
So the order of preference would be that any declarations in the second sheet would be the most important, followed by any in the sheet @imported by the second stylesheet, followed by declarations in the first stylesheet, and finally anything in the sheet @imported by the first stylesheet.

Great article! I did not realize the rules had changed (slightly) with CSS2.
One point that (still) causes me confusion [when constructing markup] is the ‘default’ values.
In other words, remembering what is ‘margin-left’ and must I override it for the desired effect.

If I’m not misunderstanding what you just said then that sounds correct :slight_smile:

The styles get imported into the page at the position they occupy in the stylesheet so the @imported files must be at the top of the stylesheet anyway and therefore the rest of the rules (if any) will follow after.

It might be clearer for argument sake to imagine that if you see a link/import to a stylesheet then just imagine those styles linked to are already present in the document at that exact position where the link is. The styles are then resolved by the normal cascade rules just as if they had always been in that stylesheet.

Therefore the fact that the styles are are brought in from elsewhere is mainly irrelevant (unless we are talking user stylesheets with !important of course).

If you had a construct like this:


<link href="test1.css" rel="stylesheet" type="text/css" />
<style type="text/css">
@import url("test2.css");
@import url("test3.css");
p{color:red}
</style>

If each of the above styles contained only one rule to define the the p element then you can just imagine that the result is as follows had you simply embedded all the styles in the page:


<style type="text/css">
p{color:blue}/* from test1.css*/
p{color:green}/* from test2.css*/
p{color:yellow}/* from test3.css*/
p{color:red}/* last in sequence */
</style>

Hope that was what you meant :slight_smile:

Believe me, there are many things about our custom article CMS that annoy me, but the one thing that irritates me the most is its inability to handle tables. I feel dirty every time I do it. I know, I know. It is on the cards to completely revamp it, with proper unicode entity support and all sorts of other magical goodness. But until that’s in place, we’re stuck with it.

Something else that would be good would be reworking comments on articles so that they display the same as they do in the forum threads, ie, all comments showing, in correct order and with quoted passages in place.

Who cares about this. Why don’t people just make sure their styles don’t conflict, and then the problem wouldn’t exist?

bohimt you’ve obviously never worked on a site that’s very complex. Or perhaps you just asign an ID to everything and have a style sheet that’s a mile long and full of redundant rules, just so that nothing conflicts, ever. Doesn’t sound very workable to me.

Couldn’t agree more Tyssen. We’re very aware of it, it’s just one thing on a long list.

Because that either gives you a very limited repartee, or means that you have to define absolutely everything individually, which is a ridiculous amount of work.

A good example is highlighting an item in the navigation bar. If your styles are:
ul#nav li {general styles} and li#current {specific styles}, the general styles have greater specificity, so will always override the li#current. But if you have ul.nav li {general styles} and li#current {specific styles}, li#current will win out.

By understanding the specificity of different combinators and rules, you can generate far more complicated and powerful stylesheets using far less code - which saves time, saves bandwidth, and makes them a lot easier to read, edit and debug.

At first glance I thought this would be another pointless article but no it really taught me something new. You are completely right in saying it is poorly documented, look at the W3C standards. Good article mate!

Thank you for the article,
I thought I understood specificity to a fine level but this showed me I had a few cracks in my knowledge, it’s a simple yet complex area of css and I’m glad I took the time in reading it.