I've worked with CSS for ages and I thought I understood specificity well, but this example baffles me; it's late at night so I might be missing something obvious:
.class span {
color: blue;
}
section#id {
color: beige;
}
<div class="class">
<section id="id">
<span>Test</span>
</section>
</div>
Specificity for section#id is 101, while for .class span is 11 and, on top of that, the second rule is even specified after the first one.
What obvious thing am I missing?
The first rule is narrowed to the span tag. The second rule is a higher level, at the parent section. So, yes, .class span will take precedence because it's hitting the actual tag.
You aren't targeting the span with the second selector. The color will only cascade to elements where the color property is set to inherit (default).
Related
What is the level of CSS specificity received by inherited properties? I read through the W3 recommendation regarding CSS specificity and so I understand how to calculate the different specificities of css rules which are directly targeting the same element, but I see no mention there of the level of specificity given to inherited attributes.
In particular, the issue I'm encountering has to do with header elements, though I would be very interested to understand this in general.
For example, here's a snippet of HTML:
<h2>This should be black</h2>
<div class="all_red_text">
<h2>This should be red</h2>
</div>
Now if I include some CSS like this:
.all_red_text { color: red; }
I will get the result I expect. On the other hand, if I the css which I included was
h2 { color: black; }
.all_red_text { color: red; }
then all the text will be black. In the first case there is some default browser CSS which is able to be overridden by the inherited property, but then when the same property is manually specified in the second example it takes precedence over the inherited property.
Any declaration that matches element directly will get priority over the property that's inherited from the element's parent. Specificity has nothing to do with that.
CSS is applied to elements in this form:
Priority 1: inline styles
Priority 2: CSS ID styles
Priority 3: CSS class/pseudo-class styles
Priority 4: CSS element styles
Priority 5: Inherited styles
So, using your HTML structure & CSS:
h2 { color: black; }
.all_red_text { color: red; }
<h2>This should be black (and is black)</h2>
<div class="all_red_text">
(This text is indeed red.)
<h2>This should be red (actually, its parent is red - this text is black)</h2>
</div>
The .all_red_text CSS is telling the div.all_red_text element and everything inside it to have red text. The h2 CSS is telling the h2 elements directly to have black text. When the h2 is rendered, it sees "my parent element wants me to have red text, but I'm directly being told to have black text". The same idea applies to further up parents, including the HTML and browser defaults - this allows you to, for example, set the font-family on the html element and have it apply to everything on your (well formatted) web page, unless something specifically overrides it.
If you want the h2 inside div.all_ted_text to also have red text, you'd need to tell those h2 elements directly to have red text; something like this:
.all_red_text h2 { color: red; }
CSS-Tricks has a pretty nice guide on this, although they don't currently go too deep into inherited properties.
There is no such thing as specificity of inherited CSS properties. Selectors, not properties, have specificity.
In your example, both h2 elements match only one of the rules, h2 { color: black; }. Thus, the color of h2 is black (assuming there are no other style sheets that affect the rendering). Anything set on some other elements (including the parent of the second h2 element) does not affect this the least.
If the rule h2 { color: black; } is absent and there are no other rules affecting the situation, then there is no color set on either of the h2 elements. According to the definition of the color property, the value is then inherited from the parent.
Two or more selectors gets engaged into Specificity War, if and only if
they end up targetting the exact same element. However, If two selectors (targetting the same element) have equal specificity weight, then there are other factors like you said, inheritance or the styles getting over ridden in the css file.
What is the level of CSS specificity received by inherited properties? I read through the W3 recommendation regarding CSS specificity and so I understand how to calculate the different specificities of css rules which are directly targeting the same element, but I see no mention there of the level of specificity given to inherited attributes.
In particular, the issue I'm encountering has to do with header elements, though I would be very interested to understand this in general.
For example, here's a snippet of HTML:
<h2>This should be black</h2>
<div class="all_red_text">
<h2>This should be red</h2>
</div>
Now if I include some CSS like this:
.all_red_text { color: red; }
I will get the result I expect. On the other hand, if I the css which I included was
h2 { color: black; }
.all_red_text { color: red; }
then all the text will be black. In the first case there is some default browser CSS which is able to be overridden by the inherited property, but then when the same property is manually specified in the second example it takes precedence over the inherited property.
Any declaration that matches element directly will get priority over the property that's inherited from the element's parent. Specificity has nothing to do with that.
CSS is applied to elements in this form:
Priority 1: inline styles
Priority 2: CSS ID styles
Priority 3: CSS class/pseudo-class styles
Priority 4: CSS element styles
Priority 5: Inherited styles
So, using your HTML structure & CSS:
h2 { color: black; }
.all_red_text { color: red; }
<h2>This should be black (and is black)</h2>
<div class="all_red_text">
(This text is indeed red.)
<h2>This should be red (actually, its parent is red - this text is black)</h2>
</div>
The .all_red_text CSS is telling the div.all_red_text element and everything inside it to have red text. The h2 CSS is telling the h2 elements directly to have black text. When the h2 is rendered, it sees "my parent element wants me to have red text, but I'm directly being told to have black text". The same idea applies to further up parents, including the HTML and browser defaults - this allows you to, for example, set the font-family on the html element and have it apply to everything on your (well formatted) web page, unless something specifically overrides it.
If you want the h2 inside div.all_ted_text to also have red text, you'd need to tell those h2 elements directly to have red text; something like this:
.all_red_text h2 { color: red; }
CSS-Tricks has a pretty nice guide on this, although they don't currently go too deep into inherited properties.
There is no such thing as specificity of inherited CSS properties. Selectors, not properties, have specificity.
In your example, both h2 elements match only one of the rules, h2 { color: black; }. Thus, the color of h2 is black (assuming there are no other style sheets that affect the rendering). Anything set on some other elements (including the parent of the second h2 element) does not affect this the least.
If the rule h2 { color: black; } is absent and there are no other rules affecting the situation, then there is no color set on either of the h2 elements. According to the definition of the color property, the value is then inherited from the parent.
Two or more selectors gets engaged into Specificity War, if and only if
they end up targetting the exact same element. However, If two selectors (targetting the same element) have equal specificity weight, then there are other factors like you said, inheritance or the styles getting over ridden in the css file.
I've looked around for information about this, but since I'm not sure of the technical names of the process, I can't seem to find an answer.
Let say I have this:
.some_class {}
.some_class .sub_div {}
<div class="some_class">
<div class="intermediate_div">
<div class="sub_div">
From my understanding, the selector .some_class .sub_div should apply to the div 'sub_div'. But it appears this is not the case as I always have to go back and change it to '.some_class .intermediate_div .sub_div'.
Is this correct or am I missing something?
My impression was that .some_class .sub_div should apply to any instance of .sub_div within the .some_class element.
.some_class .sub_div would work without any confusion. But you're actually right that .some_class .intermediate_div .sub_div would work but .some_class .sub_div wouldn't because of css specificity.
Look below for an example:
div.intermediate_div .sub_div {
color: red;
}
.some_class .sub_div {
color: blue;
}
What would you think color blue is applied? No. The red color is applied because div.intermediate_div .sub_nav higher specificity than .some_class .sub_div and thus in that case you may be wondering to see that
.some_class .intermediate_div .sub_div{
color: blue;
}
works. Because it has more specificity than previous selector.
Look more about css specificity here and in my previous answer.
CSS will apply the most specific rule to each element.
In the case of two equally specific rules, it will apply the last defined rule.
Take a look at this fiddle, which uses the following html:
<div class="some_class">
Some class
<div class="intermediate_div">
Intermediate
<div class="sub_div">Sub Div</div>
</div>
</div>
and this CSS:
.some_class {
color: red;
}
.intermediate_div {
background-color: blue;
}
.intermediate_div .sub_div {
background-color: orange;
}
.some_class .sub_div {
background-color: green;
}
All of the text is red, because some_class is red, and everything inside that div inherits that style.
intermediate_div has a blue background, which would be inherited by sub_div. But sub_div has two more specific rules defined.
Both of those rules with two class selectors are equally specific. Both are more specific than the blue background because they select based on two classes not one. The orange background is ignored, because the last defined rule is used when they are equally specific.
When you use an element id, that is more specific than a class because ids are (supposed to be) unique. So in this modified fiddle, you can see that sub_div takes styles from #div1 even though that rule is defined first and only has one selector. It still takes precedence over rules defined later and rules with two selectors, because it uses a unique id.
Say I would like to define a numbered circle, that looks like this:
http://jsfiddle.net/edi9999/6QJyX/
.number
{
border-radius: 50%;
width: 32px;
height: 24px;
text-align: center;
padding-top:8px;
font-size: 14px;
display:inline-block;
line-height: 16px;
margin-left:8px;
color:white;
background-color:black;
border-color:white;
}
I would like to add importance to the selector, so that no matter in what context the element is, an element with class number looks the same.
Here's an example of the code breaking: http://jsfiddle.net/edi9999/6QJyX/2/
A way to do this would be to add !important to all properties of the CSS, but I wonder if they could be other solutions, because it is a bit crappy.
I have added the private tag as that seems a bit like code-encapsulation.
Your best option is to increase the specificity of the selector. Other than that there is not much you can do.
#id .number
The ID selector will increase specificity so that only another ID in a selector will be able to override it.
http://jsfiddle.net/6QJyX/3/
Increasing the specificity of selectors will only lead to specificity wars (which leads to anger, which leads to hate, which leads to suffering). I would suggest decreasing the specificity of the selector that's causing the problem.
Pseudo code below:
.number {...}
.card span {...} // this selector is questionable
<div.number> this is styled correctly </div>
<div.card>
<span.number> this is styled incorrectly </span>
</div>
Why do all .card spans need to be styled a particular way? It seems as if the second selector is more like a grenade and less like a sniper—that is, it targets a blanket set of elements rather than just the ones you need.
How can I set the style of only the first div that has class "bla"? (not the second).
<div class="outer">
<div>
....(more div's, unknown how many)
<div class="bla">
....
<div class="bla">some content</div>
</div>
....
</div>
</div>
I'm assuming with this answer that by adjacent elements you mean sibling elements. If you were referring to parent-child elements then go with N1xx1's answer. That being said...
You can't target the first bla with css selectors alone. But you can target all the blas but the first. So, one possibility is to set the styles you want only on the first bla on all blas. Then override those styles by targeting all blas but the first. Like so:
.bla {
...styles for the first bla..
}
.bla ~ .bla {
...override styles set on first bla that you dont want on the others
}
The tilde between the two ".bla"'s is called the general sibling selector. If you've never heard of it, head on over to css selectors spec.
You can do simple workaround for this since you can't do that with any special selector:
.bla {
/* style here, example: */
background-color: #f00;
}
.bla .bla {
/* negate the style, example: */
background-color: transparent;
}
I hope this is what you were looking for.
According to pure css, you can't select according to the ordering of the html elements. Search the spec (here: http://www.w3.org/TR/CSS2/selector.html). There is nothing that refers to how many or in what order html elements match the given selectors.
Javascript:
getElementsByClass('bla')[0].style
EDIT: JOPLOmacedo provided a CSS only (better) answer
I've also found a way to select for instance the second <p> after a <h1> tag:
h1 + p + p{
background: red;
}
Just thought I'd share that.