The CSS universal selector (*)

In CSS, * selects every element. Its best-known job is the box-sizing reset, *, *::before, *::after { box-sizing: border-box; }. It adds zero specificity, so any other selector that targets the same element wins.

Common patterns

Selector Selects
* Every element on the page
.card * Every element inside .card, at any depth
.card > * Only the direct children of .card
* + * Every element that comes right after a sibling, nicknamed the "lobotomized owl"
*::before, *::after The generated ::before and ::after content of every element
[class*="icon-"] Something else entirely: elements whose class attribute contains "icon-"

The * + * pattern is a neat way to space out a stack without adding a margin above the first item or below the last:

.stack > * + * {
  margin-block-start: 1rem;
}

The box-sizing reset

By default, width sets the size of the content box, and padding and borders are added on top. This reset makes width include them, which is how most people expect sizes to work:

*,
*::before,
*::after {
  box-sizing: border-box;
}

The pseudo-elements are listed separately because * doesn't match them. On its own, * only selects real elements.

Specificity: zero

* counts for nothing when browsers decide which rule wins. In this example the paragraph is blue, even though the * rule comes later:

p { color: blue; }
* { color: red; }

That makes * safe for low-priority defaults. Combined selectors keep the specificity of their other parts, so .card * is exactly as strong as .card. :where() is the other zero-specificity tool, and it's handy for a reset that should be easy to override: :where(ul, ol) { padding-left: 0; }.

* really means every element

It matches <html>, <body>, and elements inside <head> such as <title>, <style> and <script>. Those stay invisible only because browsers give them display: none. So a rule like * { display: block; } makes the page title and the contents of your style sheets appear on the page. Scope broad rules to a container, like .content *, or use body *.

As for speed, modern browser engines handle a bare * with no measurable cost on typical pages. A rule that changes layout for every element is far more expensive than the selector that finds them.

Other asterisks in CSS

Where Meaning
calc(2 * 1rem) Multiplication. Unlike + and -, * and / don't need spaces around them inside calc()
[href*="example"] Attribute contains a substring
/* note */ A comment. CSS has no // comments
@namespace and *|svg The "any namespace" prefix, mostly seen in SVG and XML styling