CSS class repetition to increase specificity
Yes, it is possible and intentionally so. While this is not mentioned in the CSS2 spec, it is explicitly mentioned in the Selectors 3 spec:
Note: Repeated occurrances [sic] of the same simple selector are allowed and do increase specificity.
Therefore browsers must increase the specificity when encountering repeated simple selectors, as long as the selector is valid and applicable. This not only applies to repeated classes, but also applies to repeated IDs, attributes and pseudo-classes.
Given your code, .qtxt.qtxt.qtxt.qtxt.qtxt
will have the highest specificity. The other two selectors are equally specific; combinators have no bearing in specificity calculations at all:
/* 5 classes -> specificity = 0-5-0 */
.qtxt.qtxt.qtxt.qtxt.qtxt
/* 2 classes -> specificity = 0-2-0 */
.qtxt.lalgn
/* 2 classes -> specificity = 0-2-0 */
.lalgn .qtxt
Also, the space in your last selector is the descendant combinator; the child combinator is >
.
Programmatically set CSS selector specificity
The specificity of a selector is determined solely by its component simple selectors (and pseudo-element, if any). You cannot change the specificity of a selector without altering the selector itself.
If you're worried about changing the meaning of a selector (or its set of potential matches), there are certain dummy simple selectors that you can add while keeping the semantics intact. In your example, you can increase the specificity of UL OL LI
to match UL OL LI.red
without actually taking a dependency on an arbitrary class name by either adding an unqualified :root
to the beginning of the selector (with a descendant combinator) or adding :nth-child(n)
to any one of the three type selectors — both are guaranteed matches, and pseudo-classes are equally specific to class selectors.
Also see my answers to the following questions for more options:
- Can type selectors be repeated to increase specificity?
- CSS class repetition to increase specificity
There is no similar way to decrease selector specificity, however, neither programmatically nor by altering the selector (except of course by removing redundant selectors like the aforementioned unqualified :root
, :nth-child(n)
, or repeated type/class selectors).
Tersest way of increasing CSS selector' class-level specificity without altering selector scope
The best I can come up with is :nth-child(n)
, in that it resolves to a meaningless statement which translates into plain English as 'a child element', which will always be the case of nested fractions. The code to implement this looks like this:
.line > :nth-child(1):nth-last-child(4),
.line > :nth-child(2):nth-last-child(3),
.line > :nth-child(3):nth-last-child(2),
.size1of4:nth-child(n):nth-child(n):nth-child(n) {
width:25%;
}
The selector is specified 3 times over such that it trumps the previous selectors by 1, meaning it can also trump the next rule governing .size1of5
.
As a SASS mixin:
Because this is a verbose hack, I've packaged it up as a SASS mixin:
@mixin increase-specificity( $depth: 1 ) {
$sel : '';
@while($depth > 0) {
$sel : $sel + ':nth-child(n)';
$depth : $depth - 1;
}
{$sel} {
@content;
}
}
Increase specificity weight with double selector via Sass
There's a special trick in SASS for doubling specificity using interpolation brackets (more on that here and here) since two &
's next to each other is invalid SASS syntax.
.parent {
&__child {
{&} {
color: red;
}
}
}
// compiles to
// .parent__child.parent__child { color: red; }
// You can also do this with deeper nested elements by
// prefacing the interpolation with the ancestor selectors:
.parent {
&__child {
.some .ancestor .elements {&} {
color: red;
}
}
}
// compiles to
// .some .ancestor .elements .parent__child.parent__child { color: red; }
For those of you who stumble upon this and use LESS, double &&
's are allowed:
.parent {
&__child {
&& {
color: red;
}
}
}
Nesting CSS selectors without increasing specificity
These days, in 2018, this is getting close to possible.
First of all, CSS4 will have a way that allows you to create more specific selectors without increasing specificity:
:where(.special-section) p {
color: red;
}
This will set the paragraph color inside .special-section
to red, but with a specificity of 001 (i.e. the same specificity that a plain p
selector would have).
The spec still calls this special pseudo-class :something()
, but chances are it's going to be called :where()
. (Side note: I really want this to be known as the "honey badger selector").
But that's still in the future.
However, there is actually a way to achieve this today, if you don't have to support IE anymore (or are happy with less-than-perfect fallbacks), and that is by using custom properties a.k.a. CSS variables.
So you want this:
.special-section p { color: red; }
.weird-font { color: magenta; }
p { color: green; }
but with the first part having a specificity that's lower than any selector with a class in it. You can do it like this:
.special-section p { --low-specificity-color: red; }
.weird-font { color: magenta; }
p { color: var(--low-specificity-color, green); }
If you run the below snippet in a modern browser, you should notice that the second paragraph is red, because it's in a special section, but the third paragraph is magenta, because it's .weird-font
-- even though .weird-font
has 010 specificity and .special-section p
has 011.
.special-section p { --low-specificity-color: red; }.weird-font { color: magenta; }p { color: var(--low-specificity-color, green); }
<p>This is a paragraph.</p>
<section class="special-section"> <p>This is a paragraph inside a special section.</p> <p class="weird-font">This is a paragraph with a weird font inside a special section.</p></section>
<p class="weird-font">This is a paragraph with a weird font.</p>
<div class="weird-font">This is a div with a weird font.</div>
CSS specificity: [parent ID] [descendant combinator (space)] [my class] more specific than [my ID]?
[My ID] is more specific than [parent ID]
No, a lone ID is a lone ID. What's important in your example is which element it is being applied to.
[parent ID] [descendant combinator (space)] [my class] more specific than [my ID]
Yes, it's valid, and it is more specific. Using the W3C's abc model:
#child { // 1, 0, 0 = 100 Specificity }
#parent .foo { // 1, 1, 0 = 110 Specificity }
#parent #child { // 2, 0, 0 = 200 Specificity }
#parent #child.foo { // 2, 1, 0 = 210 Specificity }
So, #parent .foo
will trump #child
, but #parent #child
trumps #parent .foo
#parent { /* 100 */ color: blue;}#parent .foo { /* 110 */ color: green;}#child { /* 100 */ color: red;}#parent #child { /* 200 */ color: aqua;}
<div id="parent"> <div id="child" class="foo bar">what color am I?</div></div>
Related Topics
Xhtml/Css: How to Make Inner Div Get 100% Width Minus Another Div Width
CSS Specificity or Inheritance
Position Div to Bottom of Containing Div
How to Match 3D Perspective of Real Photo and Object in CSS3 3D Transforms
Css3 Transitions on Pseudo-Elements (:After, :Before) Not Working
CSS Different Font Sizes on Different Families
How to Use Chrome Web Inspector to View Hover Code
How to Declare Dependent Style Names with Uibinder
Amp: How to Toggle a CSS Class
How to Right Align Div Elements
Pass Function or Mixin by Reference in SASS
Chrome Issue with Background-Attachment Fixed and Position Fixed Elements
Media Queries and Background Images
Stopping a CSS Animation But Letting Its Current Iteration Finish
Css: Background-Color on Multi-Line Text
Is There Any Clean CSS Method to Make Each Letter in a Word a Different Color