What is the difference between * and *|* in CSS?

In CSS, * will match any element.

Frequently, *|* is used instead of * to match all elements. This is generally used for testing purposes.

What is the difference between * and *|* in CSS?


As per W3C Selector Spec:

The universal selector allows an optional namespace component. It is used as follows:

ns|*
all elements in namespace ns

*|*
all elements

|*
all elements without a namespace

*
if no default namespace has been specified, this is equivalent to *|*. Otherwise it is equivalent to ns|* where ns is the default namespace.

So, no * and *|* are not always the same. If a default name space is provided then * selects only elements that are part of that namespace.


You can visually see the differences using the below two snippets. In the first, a default namespace is defined and so the * selector applies the beige colored background only to the element which is part of that namsepace whereas the *|* applies the border to all elements.

@namespace "http://www.w3.org/2000/svg";

* {
  background: beige;
}
*|* {
  border: 1px solid;
}
<a href="#">This is some link</a>

<svg xmlns="http://www.w3.org/2000/svg">
  <a xlink:href="#">
    <text x="20" y="20">This is some link</text>
  </a>
</svg>

In the below snippet no default namespace is defined and so both * and *|* applies to all elements and so all of them get both the beige background and the black border. In other words, they work the same way when no default namespace is specified.

* {
  background: beige;
}
*|* {
  border: 1px solid;
}
<a href="#">This is some link</a>

<svg xmlns="http://www.w3.org/2000/svg">
  <a xlink:href="#">
    <text x="20" y="20">This is some link</text>
  </a>
</svg>

As BoltClock points out in comments (1,2), initially namespaces applied only to XML based languages such as XHTML, SVG etc but as per latest specs, all HTML elements (that is, elements in the HTML namespace) are namespaced to http://www.w3.org/1999/xhtml. Firefox follows this behavior and it is consistent across all HTML5 user agents. You can find more information in this answer.


*|* represents the selector of "all elements in any namespace". According to W3C, the selector is divided into:

ns|E

Where ns is the namespace and E is the element. By default, no namespaces are declared. So unless a namespace is declared explicitly, *|* and * will select the same elements.