I am well aware of CSS specificity rules (I have gone through this page: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity), but I have an example where specificity of two elements should NOT be equal, and yet CSS rules are being applied differently depending on the nesting ordering of the html elements.
h4 small {
color: red;
}
<!-- will be red -->
<h4>
<a href="www.example.com">
<small>test</small> .
</a>
</h4>
<!-- will be blue -->
<h4>
<small>
test
</small>
</h4>
Reproduced here: https://jsfiddle.net/u39zsmx1/
h4 small should be more specific than a, yet, when the a element is the most inner nested element, its style wins. Why?
How does the nesting ordering of HTML elements affect CSS specificity?
It doesn't.
h4 small should be more specific than a, yet, when the a element is the most inner nested element, its style wins. Why?
h4 small matches the <small> element. It doesn't match the <a> element. Specificity only matters when multiple rules match the same element.
The a is blue (or purple depending on if it is visited or not). This comes from the CSS rules in the browser stylesheet.
The small is red. This comes from the CSS rules in the author stylesheet.
The text node is the colour of the element it is a child of.
After a little more digging in https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity, it turns out that while ordering is not taken into account, what matters is which elements are being targeted.
Specificity is not calculated if one of the CSS rules directly targets an element and the other does not. Inheritance is not applied in such a case.
Related
<span style="color: #21584b;"><p>Text</p></span>
That's an example of some code I have in my website. The colour is a dark green and it displays normally on my PC as well as on my Android phone. But, when viewed on an iPhone or an iMac the text is within the <p> tag appears white. I don't have any CSS in the stylesheet targeting just a <p> or a <span>. All of the CSS in the stylesheet has an additional class or an id.
I've removed the <span> tags wrapping the <p> one, but I have no way of testing it since I don't own any Apple devices myself.
So, the question is, will elements inherit inline CSS, like I've put here if they don't have any classes or ids overriding them?
Do it the other way round (span inside p), that's valid HTML and will overrule any previous properties for p:
<p><span style="color: #21584b;">Text</span></p>
Yes. If the value of a property is inherit then it will copy the value from the parent element regardless of how it was applied to the parent element.
That said, a <p> may not be a child element of a <span> element. The differences you are experiencing are likely due to different browsers recovering from your invalid HTML in different ways.
Here is the official documentation for the CSS3 :not() pseudo-class:
http://www.w3.org/TR/css3-selectors/#negation
and the proposed CSS Selectors Level 4 enhancement:
http://dev.w3.org/csswg/selectors4/#negation
I've been searching the implementation and browser support for :not(), but the only examples I found were with a single element or with a direct child of an element, e.g.:
div *:not(p) { color: red; }
The example above works when <p> is a direct child of <div>, but it does not work when <p> is a more distant descendant of <div>.
div :not(p) {
color: red;
}
<div>
<ul>
<li>This is red</li>
</ul>
<p>This is NOT</p>
<blockquote><p>This is red but is not supposed to be!</p></blockquote>
</div>
If the answer is in the official documentation above, then I didn't find/understand it. As I said, I have searched this site and the web but couldn't find any discussion about the support or lack thereof of :not() as grand-children of another element.
Is this supposed to work like I think it should?
Is this supposed to work like I think it should?
No, the behavior you're seeing is correct.
In your last example, although the <blockquote> contains a <p>, it's the <blockquote> itself that's matching *:not(p), as well as the condition that it must be a descendant of the <div>, which it is. The style is applied only to the <blockquote>, but it is then inherited by the <p> inside it.
The <p> element itself still counts against the negation, so the <p> itself is still being excluded from your selector. It's just inheriting the text color from its parent, the <blockquote> element.
Even if none of its relatively close ancestors matched the selector, you have elements like html and body to worry about as well — although you could probably just tack on a body selector in the very beginning:
body div...
This is why I often strongly advise against using the :not() selector for filtering descendants, especially when not qualified with a type selector (like div in your example). It doesn't work the way most people expect it to, and the use of inherited properties like color only serves to compound the problem, on top of making it even more confusing for authors. See my answers to these other questions for more examples:
Why doesn't this CSS :not() declaration filter down?
CSS negation pseudo-class :not() for parent/ancestor elements
The solution to the problem described is to simply apply a different color to <p> elements. You won't be able to simply exclude them with a selector because of inheritance:
/* Apply to div and let all its descendants inherit */
div {
color: red;
}
/* Remove it from div p */
div p {
color: black;
}
On Selectors Level 4: yes, :not() has indeed been enhanced to accept full complex selectors that contain combinators. Essentially, this means (once browsers begin implementing it) you will be able to write the following selector and have it do exactly what you want:
p:not(div p) {
color: red;
}
In case anyone is interested, this works in jQuery today.
The color is assigned to the blockquote, and is then inherited by the p.
:not(p) just makes it so that the styles are not directly applied. They are still inherited though.
There is one <p> tag with class .eleclass and id #eleid and i have specified 3 css to the <p> tag one specified with class second with id and third with just p declared.
p#eleid{
color:yellow;
}
p.eleclass{
color:blue;
}
p{
color:red;
}
<p id="eleid" class="eleclass">
hello para.
</p>
Now i wonder why the rule applied to p#eleid is working when css runs from top to bottom nature and at bottom color red is specified so <p> should be red in color.
Is there any css rules hidden behind it??
This problem inclues use of id not only class.
It comes down to CSS specificity.
From MDN:
Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied.
As it happens, an ID based selector has higher priority than a tag based selector. This is because an ID is more specific than a tag. In other words, the tag selector applies to all p elements, while the ID will only apply to the p with the ID.
There are ways around specificity, such as the !important keyword - however, I mostly recommend against working around specificity, as it can lead to bugs.
I'm in the Chrome Element Inspector. I know that when a CSS attribute is overriden it appears with a line-through, however is it possible to see which why it was overriden?
It's simply a matter of DOM inheritance level, a style will always apply to it's deepest child element in which it is set. For example.
<div style="background='#fff'">
<div style="background='000'">
000 takes precedence
</div>
</div>
So the "why" in this matter would be that an element further up the tree is overriding it. This concept applies to stylesheets as much as the inline example I posted.
I should note a caveat - styles flagged with the !important tag will take precedence over other styles.
Given the following code:
<div id="bla">
<p class="blubber">Johnny Bananas</p>
</div>
and the style in head of that html doc:
<style>
div#bla{background:yellow}
p.blubber{background:purple}
</style>
Why is it that the child will be coloured purple and overlay its parent?
The background property is not inherited by children by default. Therefore, the background style of div#bla does not apply to p.blubber, and p.blubber can specify its own background color independently of its parent and regardless of specificity.
And since background isn't being inherited, no overriding actually takes place.
When multiple style sheets are used, the style sheets may fight over control of a particular selector. In these situations, there must be rules as to which style sheet's rule will win out. The following characteristics will determine the outcome of contradictory style sheets.
check out the section on cascading order - http://htmlhelp.com/reference/css/structure.html
Because the specificity is the same, so the rule will apply to the p element. If you remove the p and just have .blubber, it wouldn't work.
Also, children can't override parents, so if there were more content, you'd see yellow around the p (add padding to the div).
Background color is not and inherited attribute in CSS.