I thought that pseudo-classes inherited properties from their parent element, but in practice it seems the parent element specifically selects all its pseudo-classes, even if they're not specified.
Eg, given the HTML:
ok
and CSS:
#id-selector {
color: green;
}
a:any-link {
color: red;
}
I thought that color: green would only be inherited by the pseudo-class any-link, and thus be overriden by the a:any-link selector since this is a specific selector for the pseudo-class, and specific selectors override inherited properties even if they have a lower specificity. But the output of the above is a green link, indicating that #id-selector is specifically targeting any-link, not it being inherited.
An example of a specific selector with a lower specificity overriding an inherited property with a higher specificity:
HTML -
<div id="id-has-high-specificity">
<h1 class="class-has-low-specificity">Heading</h1>
</div>
CSS -
.class-has-low-specificity {
color: green;
}
#id-has-high-specificity {
color: red !important;
}
here the output is green, which is expected, since the heading is only inheriting from the second rule, but is being specifically selected by the first rule.
I thought this same thing applied to pseudo-classes, in that pseudo-classes inherited from their parent element. But it seems from my first example that they don't, and that rather the parent element specifically selects all its pseudo-classes, even if they're not specified.
Is it the case then that pseudo-classes don't inherit any properties from their parent element, but instead the parent element specifically sets all of its pseudo-classes whenever a rule for it is defined, even if those pseudo-classes aren't specified?
CSS ascertains which selector(s) 'win(s)' following a set of order of precedence rules.
For example, from MDN:
Selector Types The following list of selector types increases by
specificity:
Type selectors (e.g., h1) and pseudo-elements (e.g., ::before).
Class selectors (e.g., .example), attributes selectors (e.g.,
[type="radio"]) and pseudo-classes (e.g., :hover).
ID selectors (e.g., #example).
So in the example given in the question:
ok
and CSS:
#id-selector {
color: green;
}
a:any-link {
color: red;
}
The color does not turn to red because the id selector takes precedence, even though the setting for a comes after in the 'cascade'.
Here's a snippet where the color does change (for this example on a hover):
#id-selector {
color: green;
}
a#id-selector:hover {
color: lime;
}
a:hover {
color: red;
}
</style>
ok
UPDATE
From comments I'm wondering if there is some confusion about pseudo elements (and classes) - they are 'part of' the one element, they are not a child of a 'parent' element.
This snippet has a parent/child and in that case the specificity as assumed in the question works:
#id-selector {
color: green;
}
a:hover {
color: red;
}
<div id="id-selector">ok</div>
Related
I'd like to understand how CSS selectors work with property collisions. How is one property selected over another one?
div {
background-color: red;
}
div.my_class {
background-color: black;
}
div#my_id {
background-color: blue;
}
body div {
background-color: green;
}
body>div {
background-color: orange;
}
body>div#my_id {
background-color: pink;
}
<div id="my_id" class="my_class">hello</div>
How does selector priority work?
I'll just toss in a link to the CSS 2.1 spec itself, and how browsers are supposed to calculate specificity:
CSS 2.1 Section 6.4.3:
A selector's specificity is calculated as follows:
count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
count the number of ID attributes in the selector (= b)
count the number of other attributes and pseudo-classes in the selector (= c)
count the number of element names and pseudo-elements in the selector (= d)
The specificity is based only on the form of the selector. In particular, a selector of the form "[id=p33]" is counted as an attribute selector (a=0, b=0, c=1, d=0), even if the id attribute is defined as an "ID" in the source document's DTD.
Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.
If the specificities are equal, then CSS 2.1 Section 6.4.1 comes into play:
Finally, sort by order specified: if two declarations have the same weight, origin and specificity, the latter specified wins. Declarations in imported style sheets are considered to be before any declarations in the style sheet itself.
Note that this is talking about when the style is defined, not when it is used. If classes .a and .b have equal specificity, whichever is defined last in the stylesheet(s) wins. <p class="a b">...</p> and <p class="b a">...</p> will be styled identically, based on the definition order of .a and .b.
Element
Class selectors
ID Selectors
Inline styles
!important
In order, 1 is the lowest specificity and 5 is the highest.
https://youtu.be/NqDb9GfMXuo will shown details to demo it.
What you are interested in is specificity.
Firebug is a great tool to help inspect this. But other browsers also have built in tools for inspecting the applied CSS rules.
You can refer the full answer here Mozilla documentation
Start from the most specific:
id selectors > class selectors > type selectors(normal h1, p tag and so on..)
!important always wins, but it is considered a bad practice.See the link above.
The best way is to experiment with it:
<!-- start class vs id -->
<p class="class1" id="id1">.class vs #id: The winner is #id</p>
<!-- upper vs bottom -->
<p id="id2">the very bottom is the winner</p>
<!--most specific is the winner -->
<p id="id3">the most specific</p>
<!--pseudo and target selector -->
<h3>pseudo vs type selector</h3>
<!-- !important is more important! -->
<h1 id="very-specific">HI! I am very important!</h1>
</body>
CSS:
#id1{
color: blue;
}
.class1{
color: red;
}
#id2{
color: yellow;
}
#id2{
color : green;
}
body p#id3{
color :orange;
}
body p{
color : purple;
}
body{
color : black;
}
h3::first-letter {
color: #ff0000;
}
h3{
color: CornflowerBlue ;
}
h1{
color: gray !important;
}
body h1#very-specific{
color: red;
}
Here's a test case.
Is the weight of first-line greater than that of first-of-type? I'm a little confused!
p::first-line {
color: green;
}
p:first-of-type {
color: blue;
}
h1:last-of-type {
color: red;
}
<div>
<p>p1contentp1contentp1contentp1contentp1<br>contentp1contentp1contentp1content</p>
<h1>h1hahaha</h1>
<h1>h1hahaha2</h1>
<p>p2content</p>
</div>
In my opinion, the first p-text should be completely blue.
::first-line is a pseudo element, which means that it behaves as if it is an element inside its parent, the p.
So CSS properties defined on the p don't even apply to the ::first-line, unless they are inherited.
In this case, the color property does inherit, but it is simply overridden by the color of the pseudo element.
I'd like to understand how CSS selectors work with property collisions. How is one property selected over another one?
div {
background-color: red;
}
div.my_class {
background-color: black;
}
div#my_id {
background-color: blue;
}
body div {
background-color: green;
}
body>div {
background-color: orange;
}
body>div#my_id {
background-color: pink;
}
<div id="my_id" class="my_class">hello</div>
How does selector priority work?
I'll just toss in a link to the CSS 2.1 spec itself, and how browsers are supposed to calculate specificity:
CSS 2.1 Section 6.4.3:
A selector's specificity is calculated as follows:
count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
count the number of ID attributes in the selector (= b)
count the number of other attributes and pseudo-classes in the selector (= c)
count the number of element names and pseudo-elements in the selector (= d)
The specificity is based only on the form of the selector. In particular, a selector of the form "[id=p33]" is counted as an attribute selector (a=0, b=0, c=1, d=0), even if the id attribute is defined as an "ID" in the source document's DTD.
Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.
If the specificities are equal, then CSS 2.1 Section 6.4.1 comes into play:
Finally, sort by order specified: if two declarations have the same weight, origin and specificity, the latter specified wins. Declarations in imported style sheets are considered to be before any declarations in the style sheet itself.
Note that this is talking about when the style is defined, not when it is used. If classes .a and .b have equal specificity, whichever is defined last in the stylesheet(s) wins. <p class="a b">...</p> and <p class="b a">...</p> will be styled identically, based on the definition order of .a and .b.
Element
Class selectors
ID Selectors
Inline styles
!important
In order, 1 is the lowest specificity and 5 is the highest.
https://youtu.be/NqDb9GfMXuo will shown details to demo it.
What you are interested in is specificity.
Firebug is a great tool to help inspect this. But other browsers also have built in tools for inspecting the applied CSS rules.
You can refer the full answer here Mozilla documentation
Start from the most specific:
id selectors > class selectors > type selectors(normal h1, p tag and so on..)
!important always wins, but it is considered a bad practice.See the link above.
The best way is to experiment with it:
<!-- start class vs id -->
<p class="class1" id="id1">.class vs #id: The winner is #id</p>
<!-- upper vs bottom -->
<p id="id2">the very bottom is the winner</p>
<!--most specific is the winner -->
<p id="id3">the most specific</p>
<!--pseudo and target selector -->
<h3>pseudo vs type selector</h3>
<!-- !important is more important! -->
<h1 id="very-specific">HI! I am very important!</h1>
</body>
CSS:
#id1{
color: blue;
}
.class1{
color: red;
}
#id2{
color: yellow;
}
#id2{
color : green;
}
body p#id3{
color :orange;
}
body p{
color : purple;
}
body{
color : black;
}
h3::first-letter {
color: #ff0000;
}
h3{
color: CornflowerBlue ;
}
h1{
color: gray !important;
}
body h1#very-specific{
color: red;
}
Here's a test case.
Up until just a few moments ago, I thought for sure that selector "distance" affected which css styles would be applied. Here's what I mean by distance:
.class-2 .target {
background-color: green;
}
.class-1 .target {
background-color: red;
}
<div class="class-1">
<div class="class-2">
<p class="target">Hello World!</p>
</div>
</div>
In this example, I guess I expected that the .target element would have a green background color--since it seems like the .class-2 .target style is more specific--at least, target is more closely inside class-2 than class 1. But this is not the case. Apparently the only thing affecting the priority is the order they were declared in.
This seems really strange to me; I guess I assumed that CSS rules were applied from the outside in, or at least that that was a factor.
What do I do when I need a classes styles to be applied based on which class it is more closely inside. Is there any way to do this?
For example, in this JSFiddle, how would I get the backgrounds to be appropriately red and green colored? https://jsfiddle.net/emsca2ww/3/
In my specific case I need this because I am using a generally 12 column grid, and I need to (in some situations) set a 16 column grid context inside that.
In this specific case you can use the child selector: >
https://jsfiddle.net/emsca2ww/7/
.class-2 > .target {
background-color: green;
}
.class-1 > .target {
background-color: red;
}
This only works for parent/child elements. Otherwise you would have to introduce more parent/child relationships if needed or rethink how you are using the selectors.
Selectors have specificity and cascade order. The above selectors have the same specificity because they are both composed of two classes. This falls back to cascade order. They exist in the same stylesheet as well, so the final priority rule is applied: order in the CSS document.
If you want .class-2 to have higher priority than .class-1, you have to move the selector after it in the stylesheet:
.class-1 .target {
background-color: green;
}
.class-2 .target {
background-color: red;
}
However, this has nothing to do with the HTML itself. There is no selector for closeness between parents and children in the HTML document. You could do something like:
.class-2 > * > .target
But this selector only works if .target is a grandchild.
There is no distance priority in CSS, the only rules for priority are:
the number of ids
the number of classes, pseudo-classes
the number of elements, pseudo-elements,
the * selector
as defined in http://www.w3.org/TR/selectors/#specificity
To achieve what you want, you need to add some classes in your css:
<div class="foo class-1">
<div class="foo class-2">
<p class="target">Hello World!</p>
</div>
</div>
.class-1 .target, .foo .class-1 .target, .foo .foo .class-1 .target {
background-color: red;
}
.class-2 .target, .foo .class-2 .target, .foo .foo .class-2 .target {
background-color: green;
}
By exemple. But if you have a lot of nesting, it could become a nightmare, and you should consider another way.
Why in the following code world is blue rather than red?
The specificity of .my_class is 0,0,1,0, but it should inherit the color of #my_id whose specificity is higher at (0,1,0,0).
#my_id {
color: red;
}
.my_class {
color: blue;
}
<p id='my_id'>
Hello
<span class='my_class'>
world
</span>
</p>
See: w3c: 6 Assigning property values, Cascading, and Inheritance - 6.2 Inheritance
An inherited value takes effect for an element only if no other style declaration has been applied directly to the element.
This style applies to an element with id="my_id":
#my_id {
color: red;
}
... and will apply (inherit) to an element nested within having class="my_class" only if its color property is otherwise unspecified.
...which no longer is the case once you declare:
.my_class {
color: blue;
}
The reason this happens is due to inheritance, not specificity.
Look at it this way, if the span didn't have that class, it would inherit the color red from the parent <p> element and "world" would be red. But note that that's due to inheritance.
When you set color for the span, via the class, that overrides the inherited value.
Specificity is for determining which rule to use in multiple competing rules. In your example, there are no competing rules for <span>, so specificity does not come into play. However, if you added this to your styles:
#my_id span {color: orange}
you would see that "world" is orange because of the specificity of the id being more than the class.
It goes based on specificity and location. The class is applied directly to the text, but the ID is further away.
For a long explanation: http://monc.se/kitchen/38/cascading-order-and-inheritance-in-css
A simpler way to think of it, specificity order applies at the same level, if a style is on a parent more local then it applies, regardless of if an ancestor has a style with higher specificity (since it's further away, or less-local).