CSS Specificity: Universal Selector and Combinators
In CSS, understanding how browsers calculate selector specificity is
essential for managing cascade conflicts and writing predictable styles.
This guide explains the specificity values assigned to the universal
selector (*) and combinators (+,
>, ~, and the descendant space), detailing
how they factor into specificity calculations and providing clear
examples of their behavior in stylesheets.
The Specificity Value: (0, 0, 0)
Both the universal selector (*) and all CSS combinators
carry a specificity weight of exactly zero
(0, 0, 0 or (0, 0, 0, 0) when accounting for
inline styles).
They add no weight to the selector chain. When a browser calculates which rule takes precedence, neither the universal selector nor any combinator will increase the specificity score of that rule.
The Universal Selector
(*)
The universal selector matches any element of any type. Despite
matching elements, it does not count as a type selector (which normally
adds 0, 0, 1).
- Weight:
0, 0, 0 - Behavior: It will style every matched element, but any selector with a higher specificity (such as a single element selector, class, or ID) will override it.
Example:
/* Specificity: 0, 0, 0 */
* {
color: black;
}
/* Specificity: 0, 0, 1 */
p {
color: red;
}In this example, paragraphs will be red because the
element selector p (0, 0, 1) outweighs the
universal selector * (0, 0, 0).
CSS Combinators
Combinators define the structural relationship between selectors rather than targeting elements themselves. Because they only define relationships, they contribute nothing to specificity.
The standard CSS combinators include:
- Child combinator (
>): Matches direct children. - Next-sibling combinator (
+): Matches the immediate next sibling. - Subsequent-sibling combinator (
~): Matches any following sibling. - Descendant combinator (
- whitespace): Matches any nested descendant.
None of these symbols add weight to the calculation. Only the selectors on either side of the combinator are counted.
Example:
/* Specificity: 0, 0, 2 (div + p) */
div > p {
color: blue;
}
/* Specificity: 0, 0, 2 (div + p) */
div p {
color: green;
}
/* Specificity: 0, 0, 2 (h2 + p) */
h2 + p {
color: purple;
}In div > p, the score is 0, 0, 2 because
there are two type selectors (div and p). The
> combinator contributes 0. The selector
div p has the exact same specificity (0, 0, 2)
because whitespace functions identically to > in terms
of weight calculation.
Breakdown of Combined Examples
To see how these rules work together, consider the following combinations:
| Selector | Breakdown | Total Specificity |
|---|---|---|
* |
Universal (0, 0, 0) |
0, 0, 0 |
*.warning |
Universal (0, 0, 0) + Class
(0, 1, 0) |
0, 1, 0 |
body > * |
Element (0, 0, 1) + Child
(0) + Universal (0, 0, 0) |
0, 0, 1 |
article > p |
Element (0, 0, 1) + Child
(0) + Element (0, 0, 1) |
0, 0, 2 |
header + nav > ul ~ p |
4 Elements (0, 0, 4) + 3
Combinators (0) |
0, 0, 4 |
Summary
When calculating CSS specificity:
- Ignore
*. It only applies styles without adding weight. - Ignore combinators (
+,>,~, and whitespace). They establish relationships between nodes but add zero weight. - Count only the actual targets, classes, attributes, pseudo-classes, IDs, and element types surrounding the combinators.