The selector weight categories are listed here in the order of decreasing specificity:
-
ID column
-
Includes only ID selectors, such as #example
. For each ID in a matching selector, add 1-0-0 to the weight value.
-
CLASS column
-
Includes class selectors, such as .myClass
, attribute selectors like [type="radio"]
and [lang|="fr"]
, and pseudo-classes, such as :hover
, :nth-of-type(3n)
, and :required
. For each class, attribute selector, or pseudo-class in a matching selector, add 0-1-0 to the weight value.
-
TYPE column
-
Includes type selectors, such as p
, h1
, and td
, and pseudo-elements like ::before
, ::placeholder
, and all other selectors with double-colon notation. For each type or pseudo-element in a matching selector, add 0-0-1 to the weight value.
-
No value
-
The universal selector (*
) and the pseudo-class :where()
and its parameters aren't counted when calculating the weight so their value is 0-0-0, but they do match elements. These selectors do not impact the specificity weight value.
Combinators, such as +
, >
, ~
, " ", and ||
, may make a selector more specific in what is selected but they don't add any value to the specificity weight.
The &
nesting combinator doesn't add specificity weight, but nested rules do. In terms of specificity, and functionality, nesting is very similar to the :is()
pseudo-class.
Like nesting, the :is()
, :has()
, and negation (:not()
) pseudo-classes themselves add no weight. The parameters in these selectors, however, do. The specificity weight of each comes from the selector parameter in the list of selectors with the highest specificity. Similarly, with nested selectors, the specificity weight added by the nested selector component is the selector in the comma-separated list of nested selectors with the highest specificity.
The :not()
, :is()
, :has()
and CSS nesting exceptions are discussed below.
Matching selector
The specificity weight comes from the matching selector. Take this CSS selector with three comma-separated selectors as an example:
[type="password"],
input:focus,
:root #myApp input:required {
color: blue;
}
The [type="password"]
selector in the above selector list, with a specificity weight of 0-1-0
, applies the color: blue
declaration to all password input types.
All inputs, no matter the type, when receiving focus, match the second selector in the list, input:focus
, with a specificity weight of 0-1-1
; this weight is made up of the :focus
pseudo-class (0-1-0) and the input
type (0-0-1). If the password input has focus, it will match input:focus
, and the specificity weight for the color: blue
style declaration will be 0-1-1
. When that password doesn't have focus, the specificity weight remains at 0-1-0
.
The specificity for a required input nested in an element with attribute id="myApp"
is 1-2-1
, based on one ID, two pseudo-classes, and one element type.
If the password input type with required
is nested in an element with id="myApp"
set, the specificity weight will be 1-2-1
, based on one ID, two pseudo-classes, and one element type, whether or not it has focus. Why is the specificity weight 1-2-1
rather than 0-1-1
or 0-1-0
in this case? Because the specificity weight comes from the matching selector with the greatest specificity weight. The weight is determined by comparing the values in the three columns, from left to right.
[type="password"]
input:focus
:root #myApp input:required