Reason for CSS property precedence? - css

I actually know how the browsers tend to render the following examples (results based on Opera 9.5 and Firefox 3.0), but I don't understand the reason behind them.
Take this example,
<style type="text/css">
#outer{color:red;}
.inner{color:blue;}
</style>
<div id="outer" class="outer">
<div id="inner" class="inner">
<span>testing</span>
</div>
</div>
The result is blue text.
However, now see this example,
<style type="text/css">
#outer span{color:red;}
.inner span{color:blue;}
</style>
<div id="outer" class="outer">
<div id="inner" class="inner">
<span>testing</span>
</div>
</div>
The text is now red.
Finally, try this,
<style type="text/css">
#outer span{color:red;}
#inner span{color:blue;}
</style>
<div id="outer" class="outer">
<div id="inner" class="inner">
<span>testing</span>
</div>
</div>
Once again we have blue text.
Is there a specific reason for this methodology?
(sorry about the unclear title, it's the best I could manage.)

In example 1 the span element is not directly targeted, so we must look into how CSS Inheritance is handled. Color is an inherited property so we need to look at the span's closest parent element to determine color. In your example 1 case, the class (.inner) has color blue defined and passes that inheritance down to the span.
In example 2 the span element is directly targeted by both rules, so we must look into the CSS Cascade to determine which of the rules that targets the element is most specific. The rule with the ID selector wins.
In example 3 we invoke the CSS Cascade rules once again and since both specificities are equal, last rule wins.
Note that in this situation:
#outer {color: red; }
span {color: blue; }
The text will be blue. This is because the second rule targets the element directly and therefore does not invoke the CSS Cascade.
More Reading:
CSS Specificity Wars
Understanding Specificity
CSS for Poker Players
Note and Disclosure: I authored the third blog post.

The W3C has a detailed explanation of exactly how CSS is supposed to cascade and take precedence. For your exact situation, this is what is occurring:
While "color" is an inherited property, the inner selector targets the span itself, so it takes precedence.
Since they both now target the span, the one that is more specific (the id selector) now takes precedence.
They are now both equally specific, and thus the declaration that appears later takes precedence.

I hope this explanation helps:
EX 1) Because these are general rules, it applies the color of the immediate parent .inner
EX 2) An ID is more specific than a class (since there is only one element with a given ID) therefore the id selector is considered more specific and important
EX 3) Because the 2 rules are equally specific it chooses the last rule
Darko

In the first example the first style applies to the outer div. The inner div then inherits this style, but the second style applies to the inner div so it overrides the inherited style.
In the second example both styles apply to the span. The first style takes precedence because an id is more specific than a class.
In the third example both styles also apply to the span. As they have the same specificity, the last style takes precedence just because it's last.
You can read more about how precedence is determined here.

The cascade (the the 'C' in CSS) is well defined to allow a clear definition of what rules will take precedence (including allowing for important, user and agent rules).
But the rules are also not simple (thing of complex matches with large hierarchies specified).
The last step of the cascade is document order of the declaration, with last winning.

Related

What does text before selectors in css mean?

Apologies for the beginner css question but it's rather difficult to find an answer for this.
I'm looking at the duckett book for html and css and it has a couple of selector syntax confusing to me.
table.one{}
input#web{}
I thought that the .x indicates that x is a class selector and similarly that #x indicates that x is an id selector but why did the author choose to put text before these? He didn't give an explanation as far as I can tell.
table.one matches all table elements which have class one.
input#web matches the input element which has id web.
This kind of selector is called "Type selector". You can read these resources:
CSS2.1 spec
Selectors Level 3
Selectors Level 4
MDN article
table.one{}
'[element type].[css class name]{}
input#web{}
'[element type]#[id attribute]{}
When an element type is specified, that means that definition will only work for that element type.
table.myCss{} for the Element, when class='myCss' then apply the css. Don't apply this CSS to <span class='myCss'> or any other element type.
Here is a link to the official specifications page for CSS3. http://www.w3.org/TR/css3-selectors/
Let me break it down:
table.one means, look for a tag with the name table, which also has the class one
input#web similarly means: look for an element with the name input and the id of web
In some cases, these selectors might not be necessary, especially on IDs, since they are supposed to be unique, as opposed to classes, which are reasuable. The usage of element names with classes, however, can help you make different elements look different than others, for example, if you want to center text and a div, you might only want to use one class for both, but since <div> elements are block level, they can't be center like text by default.
div.center {
margin-left: auto;
margin-right: auto;
}
p.center {
text-align: center;
}
<input class="x" ... >
<div class="x" ... ></div>
So now we have:
.x {} // To select both
input.x {} // To select just the input with class "x"
div.x {} // To select just the div with class "x"
This could be used to just make it more clear for what element the styles are for. Or to limit the elements affected.
Similarly we can do this with element ids.
<input id="a" ... >
<div id="b" ... ></div>
So we can write simply #a. Or we can write input#a. Currently these are equivalent.
With the div we would have either #b or div#b.
The use of table and input in front of their respective classes / IDs reference the type of element in the markup. For example:
table.one {
..
}
References a table with class "one" (in code: <table class="one">). This way, if the author has another element with class "one" (example: <div class="one">), the div is not affected by the rule of table.one.
Same idea for input#web, except the selector is targeted towards input tags with ID of "web" (<input id="web">)
Some additional reading from W3 may be of some help (it's from CSS2, but the main points are still present): http://www.w3.org/TR/CSS2/selector.html
DEMO: http://jsfiddle.net/uWkYL/

CSS combinator not working - Differnce of one space?

I have two carousels on a page and need to style them differently. So I have this css combinator to style a child bootstrap element inside an id element...
#menuCarousel .carousel { ...
Which doesn't work as I expected. However, if I close the space like this...
#menuCarousel.carousel { ...
the styles are applied. According to W3Schools, there is meant to be a space so I'm thinking I'm doing something else wrong.
What's happening here y'all?
Thanks.
Just in case the html is important:
<div id="menuCarousel" class="carousel slide" data-ride="carousel" data-interval="false">
First off in this case the .carousel shouldn't be necessary at all, because IDs must be unique and that alone would be sufficient to select the div.
But to get down to your question, a space between CSS selectors will select a descandant element. Removing the space means to select the element with that class.
So #menuCarousel .carousel { ... says select all elements with the class carousel that are descendants of the element with the ID #menuCarousel.
#menuCarousel.carousel { ... means select the element that has the ID menuCarousel AND the class carousel.
(And on a side note, don't use w3schools to learn CSS. Use https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors)
The id= (#) and class= (.) are applying to the same element, so I would think they would have to be combined as #menuCarousel.carousel. Otherwise it would be looking for a .carousel under a #menuCarousel, wouldn't it?
So a space indicates a nested element like this
<div id="parent" class="parent">
<div class="child"></div>
</div>
#parent .child{background-color:blue;}
The above example would make the child element blue.
However two selectors without a space is used to select an element using two different selectors on the same element. So
#parent.parent{background-color:blue;}
Would make the parent element blue in the same way as just #parent

Why does this selector not work

Given the following markup
<div class="fixed">
<div class="clmn2">
</div>
<div class="clmn2">
</div>
</div>
And the information given on mdn
By my interpretation this selector should work.
*:not(.fixed) [class*="clmn"]
Unfortunately it does not, however this does.
div:not(.fixed) [class*="clmn"]
Any ideas why?
*Update *
If you check the linked fiddle the column in rows not marked with the class fixed should be floated.
*:not(.fixed) foo matches
A foo element that is a descendant of any element that is not a member of the fixed class
This is different to:
A foo element that is not a descendant of any element that is a member of the fixed class
If we had:
<a class="fixed">
<b>
<foo></foo>
</b>
</a>
Then the foo element is a descendant of a b element that is not a member of the fixed class. (It is also a descendant of an a element that is a member of that class, but that doesn't matter because *:not(.fixed) will happily match the b element instead.)
Your "bad" selector matches any element with a class as given that is a descendant of any element without class fixed.
Since both the <html> and <body> elements do not have the class fixed and your inner <div>s are their descendants, the selector matches them.
The "good" selector only considers descendants of any <div> that does not have the class fixed. Since the only <div> in your HTML that has descendants also has that class, the selector matches nothing.
In general, plain :not(whatever) followed by a descendant combinator is not really useful. In your case it looks like the solution would be to replace the "descendant" combinator with the child combinator >:
:not(.fixed) > [class*="clmn"]
Your selector is too general. Since * will also select things like body. And body is not(.fixed), the rule will still be applied.
Change it to something more specific like .row:not(.fixed).
http://jsfiddle.net/sVpTA/2/
CSS
.row:not(.fixed) [class*="clmn"]{
float: none;
width: 100%;
margin-left: 0!important;
}
Actually, it's working better than you want it to.
*:not(.fixed) matches, among other things, your body element. Eventually, somewhere within the body, it finds your clm* divs, and applies the styles.
If you only want to match things that are direct descendants of something non-fixed, use:
*:not(.fixed) > [class*="clmn"] { /* ... */ }
Which does work.

Using CSS selector specifity over selector ID's?

In class we are teached to avoid creating ID's in your HTML so you can use them to identify that element in your CSS file. Instead we must use selector specifity as much as possible.
Take for example this simple HTML:
<body>
<div>
<div>
<div>
The div you want to style.
</div>
</div>
</div>
</body>
Is it better to use this:
body > div > div > div{
color: blue;
}
or give the element an id (let's take 'middle') and use this:
#middle{
color: blue;
}
What are the differences (if any at all) performance and usability wise?
The difference in speed between IDs and Classes in modern browsers is so negligible in real world situations it is really not an issue. Therefore current main-line thinking is to use classes where extra clarity and specifity is needed. This way you avoid specifity wars and balances maintainability with code purity.
<body>
<div>
<div class="more-specific-if-needed">
<div class="middle">
The div you want to style.
</div>
</div>
</div>
</body>
.make-more-specific-if-needed .middle {
/* cool styles */
}
Or even use chained selectors to gain extra specifity. You could then split styles in to separate structure based build styles and appearance based theme styles.
<body>
<div>
<div>
<div class="semantic-role theme">
The div you want to style.
</div>
</div>
</div>
</body>
.semantic-role.theme {
/* cool styles */
}
For further reading:
http://csswizardry.com/2011/09/writing-efficient-css-selectors/
Why do browsers match CSS selectors from right to left?
Performance wise it's fastest to get an element by its id than it is to traverse the dom.
From a usability point of view I would be careful using too many id's since they can be only used once for an element.
So it's a question of what you think is more important and how many items we are talking about. Is the speed gain worth the losing of re-usability
Much better to use ID. Performance difference is minimal, and not the important point. I think code readability / maintainability is more important.
One advantage of using ID, is that you could move your element to a different part of the page, and it would retain it's style rules - without counting the containing elements.

CSS Match Regular Expression and last-child

I am trying to match all elements with a class of span1, span2, span3, span4 and so on.
I am using the following code, but it does not match the last child of these classes:
[class*="span"]:last-child{
margin-left:0;
}
For example if I have:
<div>
<div class="span3"></div>
<div class="span9"></div>
<div class="clearfix"></div>
</div>
The rule does not apply to the .span9 element.
last-child works on whatever the last child of the parent is. In your example, it's looking at the last div and seeing that its class is clearfix - not something with span in it - and failing to match.
If you're always clearfixing at the end and you only want to target the second-to-last child, then you could use.
nth-last-child(2)
which would, as its name suggests, target the 2nd-to-last element, regardless of what it is. View on JSFiddle.
If you're always working with divs, you could also use this code to get the same effect:
nth-last-of-type(2)
View that one on JSFiddle.
The IE support for all of these patterns (last-child, nth-last-child, and nth-last-of-type) is the same, IE9 or later.
Though, of course, you can simply get rid of the :last-child bit to target all of your span class divs, regardless of where they are within the parent:
[class*="span"]
View on JSFiddle

Resources