Specificity rules for comma delineated lists - css

When using Cascading Style Sheets I have observed the order of specificity as follows:
1st Laws: In-line Styles
2nd Laws: Number of ID Selectors
3rd Laws: Number of Class Selectors
4th Laws: Number of Element Selectors
So, items with in-line styles came first, followed by declarations with one or more ID selectors, followed by declarations with one or more class selectors, followed by declarations with one or more element selectors. With more IDs, classes and elements meaning more precedence, respectively.
From this viewpoint I was unable to comprehend where comma delineated lists of IDs, classes or elements fit. Does a comma delineated list have any special precedence rules? Also, in a single comma delineated list, are IDs, classes and elements considered separate items, for the purposes of calculating specificity?
Code example:
html, body, header {
position: absolute;
top: 0px;
}
header {
position: relative;
top: 50px;
}
What takes precedence in the above example? Is the comma delineated list treated as referencing a single element, in which case the header would take precedence simply for being last in the cascade, or is the comma delineated list treated as multiple elements, and therefore takes precedence? Or are there other rules I should be considering first?

Does a comma delineated list have any special precedence rules?
Strictly speaking, a selector-list does not have its own specificity value, but for the purposes of the cascade, the specificity of a selector-list is equal to the specificity of the most specific selector that matches the element. This is not stated explicitly in the current specification, but it appears in selectors-4. Even so, since a selector-list is nothing more than a way to combine two or more selectors in a single expression without having to repeat their style declarations, it makes sense why it would work this way.
Remember that a selector is only relevant to an element when it matches the element — otherwise, it never enters into specificity calculations, or any part of the cascade.
Also, in a single comma delineated list, are IDs, classes and elements considered separate items, for the purposes of calculating specificity?
Every simple selector has its own specificity value, but these values are added up at the complex-selector level. A complex selector is one part of a selector-list. For example, the selector-list
.foo > .bar, nav input:checked + label
has two complex selectors:
.foo > .bar, with a specificity of (0, 2, 0)
nav input:checked + label, with a specificity of (0, 1, 3)
What takes precedence in the above example? Is the comma delineated list treated as referencing a single element, in which case the header would take precedence simply for being last in the cascade, or is the comma delineated list treated as multiple elements, and therefore takes precedence?
In your example, the selector-list html, body, header consists of three separate lone type selectors. Since every element can only be of one element type at a time, it's easy to deduce that all three selectors in the list are mutually exclusive, i.e. an element can only match one of any of the three selectors at a time (or none at all). A header element can never match the html or body selectors, and so neither of those selectors is relevant. You just have the header selector to deal with, and specificity becomes less of an issue in your example. The result is that your second rule, with just the header selector, takes precedence, because the only two selectors that are relevant are equally specific.
But this becomes more pertinent when you have a selector-list that consists of more than one selector that can match the same element. Let's pretend that both selectors in my example above can match the same label element. So we have two selectors of specificity (0, 2, 0) and (0, 1, 3) that both match the same element. As in the first paragraph of my answer, the specificity is equal to that of the most specific selector, (0, 2, 0). It is not, as one might otherwise have guessed, the total specificity of all matching selectors (0, 3, 3), or the specificity of the least specific (which wouldn't really make sense anyway).
This means, for example, that a separate rule with a selector whose specificity is (0, 3, 0) will still take precedence over the selector-list, even if both selectors in that list match the same element. Consider this contrived example (you'll rarely find examples of this in the wild):
.foo > .bar.baz {
color: red;
}
.foo > .bar, nav input:checked + label {
color: blue;
}
<nav class="foo">
<input type="checkbox" id="check" checked>
<label for="check" class="bar baz">Checkbox</label>
</nav>
Notice that regardless of whether the checkbox is checked, the label never turns blue. This is because .foo > .bar.baz has a specificity of (0, 3, 0) which is higher than each of the two individual specificities given above, even though it's lower than the combined specificity, since specificities are never combined this way.

Remember that CSS is cascading - meaning the style that is referenced FURTHER down a CSS file will take precedence assuming the selector is the same:
header {
background-color: red;
}
p, span, header {
background-color: yellow;
}
<header>
HEADER
</header>
If we switch around the declarations above, the opposite happens:
p, span, header {
background-color: yellow;
}
header {
background-color: red;
}
<header>
HEADER
</header>
As you can see, comma separated selectors / declaration make no difference - they're treated the same as if you'd done them singly.

In CSS separating rules by , means listing multiple selectors. So html, body, header style will be applied to every html, body and header no matter if some of it is missing or not. It will not provide any precedence to selector.
In your example header position will be absolute just because first rule will have lower precedence than second. Same as:
header {
position: relative;
}
header {
position: absolute;
}

I this case both of them are Element Selectors so the outputted css would be bottom one because css is rendered from top to bottom precedence in this case takes last element.

Related

Why does putting comma selectors inside a space selector break the parent?

I am used to using descendant space selectors and comma selectors. I have ids around larger sets of elements in order to manipulate them easier in jquery and css.
So I tried something like this:
#parent_id input, textarea
{
width: 100px;
}
So when I do this, my expectation is that this effect will occur on input AND textarea inside the #parent_id. Instead, this disqualifies parent_id and just selects all input, textarea. Why? And how can I avoid this, aside from making them separate.
In CSS, rules have the form:
selector0 [, selectorN ]*
{
property0: value0[,
property1: value1]*
}
So the comma , is used to separate different selectors for the same property set. For example, if you wanted two radically different selectors for the same property set.
Selectors in CSS must be fully-qualified, there is no contextual-sensitivity - this is partly because CSS is designed to be forward-compatible: browsers are instructed to try each and every selector in a rule independently, so browsers gracefully-degrade when they encounter new selector syntax they don't support.
To get the effect you want just type more :)
#parent_id input,
#parent_id textarea {
width: 100px;
}
Note that there is a proposed/experimental :matches() selector function which works as a logical OR operator in selectors, it's in the CSS Level 4 Selectors specification (currently in a working-draft state, as of 2016-05-04: https://drafts.csswg.org/selectors-4/ ).
The matches-any pseudo-class, :matches(), is a functional pseudo-class taking a selector list as its argument. It represents an element that is represented by its argument.
So in your case it would be:
#parent_id :matches( input, textarea ) {
width: 100px;
}
But I don't think this usage is really that better, it's less obvious and requires greater knowledge of CSS.

Overriding combined css classes

There are numerous questions about the order of loading CSS files and overriding classes, but after reading them I still have something I can't figure out.
There are two CSS files:
<link rel="stylesheet" href="standard.css" type="text/css">
<link rel="stylesheet" href="override.css" type="text/css">
loaded in this order (I checked that).
The HTML looks like this:
<div class="div_D1 ov_D1">
<div class="div_D2 ov_D2">
<div class="div_D3 ov_D3">
blablah
</div>
</div>
</div>
Standard.css contains:
.div_D1{
background: white;
}
.div_D2{
height: 10px;
}
.div_D1 .div_D3{
padding-left: 20px;
}
Override.css contains:
.ov_D1{
background: red;
}
.ov_D2{
height: 50px;
}
.ov_D3{
padding-left: 0px;
}
.ov_D1 and .ov_D2 are applied correctly: the background of .div_D1 is red, the height of .div_D2 is 50px.
.ov_D3 on the other hand does not behave as I expected. If I look at the order the rules are applied, the browser first applies .ov_D3, and then .div_D1 .div_D3, leaving me with an unwanted padding of 20px.
If however I change the class selector in Override.css to
.div_D1 .ov_D3 it does remove the padding.
Also changing the css to
.ov_D3{
padding-left: 0px; !important
}
does the trick. So there are solutions, I only can't understand why with a single selector the order of loading is respected, and with multiple selectors it is not.
This is called specificity of a Selectors. From the book Beginning CSS: Cascading Style Sheets for Web Design, Third Edition by Ian Pouncey and Richard York:
In addition to style sheet precedence, an order of precedence exists for the selectors contained in each style sheet.
This precedence is determined by how specific the selector is.
For example, an ID selector is the most specific,
and the universal selector is the most general. Between these, the
specificity of a selector is calculated using the following formula:
Count 1 if the styles are applied from the (X)HTML style attribute, and 0 otherwise; this becomes variable a.
Count the number of ID attributes in the selector; the sum is variable b.
Count the number of attributes, pseudo-classes, and class names in a selector; the sum is variable c.
Count the number of element names in the selector; this is variable d.
Ignore pseudo-elements.
Now take the four values and put them together in groups of four.
For Example:
Selector : div.someclass.someother
Selector Type : Element Name + Class Name + Class Name
specificity:
0,0,2,1, (a = 0, b = 0,
c = 2, d = 1)
In CSS, there are rules for specificity (quoted from MDN):
The following list of selectors is by increasing specificity:
Universal selectors
Type selectors
Class selectors
Attributes selectors
Pseudo-classes
ID selectors
Inline style
Since you have added specificity to your Selector you weren't able to override by normal CSS class selector.
So your Code
.div_D1 .div_D3is more specific than.div_D3and less specific than.div_D3.ov_D3.
JS Fiddle
As per MDN CSS selectors have rules called 'Specificity' which determine their order of precedence. The more specific a rule is, the greater it's priority regardless of position within a/some stylesheet(s).
A rule such as .class-1 .class-3 has a specificity (it's more specific) higher than .class-3 and takes precedence, as such the less-specific rule cannot override it without the use of !important which negates all other specificity rules. Using the higher specificity rule only takes place with conflicting styles, however.
So, you have set the rule:
.div_D1 .div_D3 { }
The above rule is more specific than:
.ov_D3 { }
Even though they target the same element the rule with the higher specificity takes precedence. You can fix this in your JS Fiddle by prepending the appropriate class structure as defined above.
So, .ov_D3 becomes either:
.div_D1 .ov_D3
or
.ov_D1 .ov_D3
Example here: JS Fiddle

Why does an earlier CSS rule override a later rule?

In my stylesheet, .four-across li defines width: 174px; at line 8806. Below that rule at line 9603, .no-search-results defines width: auto;. However, the 174px rule is overriding an element with .no-search-results. Why would that be?
You should read about CSS specificity.
.four-across li is more specific than .no-search-results, so it have higher importance level.
Specificity is calculated by counting various components of your css
and expressing them in a form (a,b,c,d). This will be clearer with an
example, but first the components.
Element, Pseudo Element: d = 1 – (0,0,0,1)
Class, Pseudo class, Attribute: c = 1 – (0,0,1,0)
Id: b = 1 – (0,1,0,0)
Inline Style: a = 1 – (1,0,0,0)
by Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade
Document order matters only when given specificity is exactly the same. In you example first selector is (0,0,1,1) and second is (0,0,1,0), so the first one overrides the second one, no matter how are they ordered within CSS document.
Read:
Reviewing CSS Style Priority Level
Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade
In this case it's because a class and an element type are more specific than just a class, and it's favored over the order.
Two reasons:
The last rule scanned has precedence over those scanned previously, all else being equal.
The more specific the rule is (two specifiers as opposed to one) the higher the precedence.

Why does bootstrap accept form styling for only one highly specific css classes?

I have a jsbin with a table of inputs, using bootstrap. What confuses me is that the style with
input.someClass {
background-color: blue;
}
is applied, as expected, but
.anotherClass {
background-color: green;
}
is not applied to my input elements. What is the reason for this? For reference, check out http://jsbin.com/enaris/3/edit
What is the reason for this?
It's simply a matter of specificity - the first selector has a type selector attached to the class name whereas the second selector only has a single class. The second selector is therefore more specific and takes precedence.
This is migrated from another answer of mine, it may help:
You can think of specificity as four numbers, starting with (0,0,0,0):
!important rules always take precedence, only another !important rule
can override a previous one (its an accessibility feature of CSS,
designed to override the UA stylesheet)
The universal selector (*) has a specificity of 0
Combinators like + and ~ also have no specificity
Inline styles have the highest specificity (other than !important)
and count as the first number (1,0,0,0)
ID's (#test) count as the second number in the above set (0,1,0,0)
Classes, pseudo-classes and attribute selectors are the third number
(0,0,1,0)
Type selectors and psuedo-elements (e.g. - <p> & ::after) take place of the
fourth number, and are the least specific
Remember that if two rules have the same specificity and specify the
same property the latter in the stylesheet will win
Based on the above, the first selector has a specifictiy of (0,0,1,1) while the second only has (0,0,1,0)
CSS rules are applied from least specific to most specific.
You have:
Least Specific More Specific Most specific
.anotherClass input[type=...] (bootstrap) input.someClass
So, in your example b-cell is more specific than bootstrap styles and a-cell is less.
You can force a-cell to take precedence with !important (but use !important with caution, as it might become a debugging hell):
.a-cell {
background-color: green !important;

Why does the :nth-child(2) selector work on what I expect to be :first-child?

I have an example of what I'm trying to ask.
I use this kind of format often. I'd expect to be able to select that first div with fieldset div:first-child { } but it seems that it's only grabbed by the 2nd child selector. I would expect "field 1" to be red and not blue. It makes more sense semantically (to me at least) to say "style the first div in the fieldset like so" instead of saying the 2nd.
Why is this happening and is there a way to achieve the effect I want (to be able to call div:first-child)?
The :nth-child selector ignores the elements type. div:nth-child(2) selects a <div> which is a second child.
If you want to select the first div, use the :nth-of-type(1) or :first-of-type selector.
Demo: http://jsfiddle.net/Z3Bcq/1/
In this case, the <legend> preceding the first div is the actual :first-child of their shared parent. You could consider using the :nth-of-type selector.
Fiddle here
Here is the explanation how :nth-child selector works:
This pseudo-class matches elements on the basis of their positions within a parent element’s list of child elements. The pseudo-class accepts an argument, N, which can be a keyword, a number, or a number expression of the form an+b. For more information, see Understanding :nth-child Pseudo-class Expressions.
If N is a number or a number expression, :nth-child(N) matches elements that are preceded by N-1 siblings in the document tree.
The following example selectors are equivalent, and will match odd-numbered table rows:
tr:nth-child(2n+1) {
⋮ declarations
}
tr:nth-child(odd) {
⋮ declarations
}
This example selector will match the first three rows of any table:
tr:nth-child(-n+3) {
⋮ declarations
}
This example selector will match any paragraph that’s the first child element of its parent element:
p:nth-child(1) {
⋮ declarations
}
This is, of course, equivalent to the selector p:first-child.
Note: For more details on selector please see the link: http://reference.sitepoint.com/css/pseudoclass-nthchild

Resources