CSS Universal Selector * - Performance and Practical Use

The CSS universal selector * matches every element. Learn its real performance impact, common reset uses, and when scoping with :where(*) is the safer choice.

Concepts

Detailed Explanation

What * Actually Does

The universal selector matches every element in the document. By itself it's used for resets and inheritable defaults:

* {
  box-sizing: border-box;
  margin: 0;
}

It also appears as a wildcard inside compound selectors:

.grid > *   { /* every direct child */ }
[data-foo] * { /* every descendant of any element with data-foo */ }

The "Performance" Myth

Old-school CSS guides warned that * was slow. Modern browsers (Blink, WebKit, Gecko) match selectors right-to-left and use highly optimized hash maps for the rightmost compound. A bare * is essentially free; the cost only adds up if you write deeply qualified selectors that force the engine to walk the tree:

* * * { color: red; } /* still fine */
.deep > * + * + * { } /* slightly slower because of sibling walks */

In practice you should never feel * performance unless you're writing pathological selectors on a five-figure-node DOM.

Specificity Is Zero

* contributes (0, 0, 0) to specificity. That makes it ideal for resets — anything else will override it.

Owl Selector * + *

The "lobotomized owl" pattern from Heydon Pickering uses the universal + adjacent-sibling combo to add a top margin between flow elements:

.flow > * + * { margin-top: 1.5em; }

It's a single rule that creates consistent vertical rhythm without per-element styles.

Scope With :where(*)

If you want a wide-reaching rule but worry about specificity collisions, wrap in :where():

:where(*) {
  font-family: system-ui, sans-serif;
}

The selector still matches every element but contributes zero specificity (which it would have anyway in this case — but it documents intent).

When NOT to Use *

  • Inside very large ancestor selectors that force a walk: section nav ul li * — costly because the engine matches every element then climbs four ancestors.
  • For inheritable properties, prefer setting them on html or :root so inheritance does the work.

Use Case

Use the universal selector for box-sizing resets, the owl pattern for vertical spacing, and as a wildcard inside compound selectors (".grid > *", "[data-tooltip] *"). The performance fear is outdated; pick "*" when it expresses intent more clearly than alternatives.

Try It — CSS Selector Reference

Open full tool