Namespaces, as part of the document language, do not apply directly to pseudo-classes or pseudo-elements, as they're defined in CSS and not the document language (e.g. XML). Element types and attributes, however, are defined in the document language as opposed to CSS, which is why they can be namespaced. Consequently, in a sequence of simple selectors, the universal selector specifically means "any type".
The universal selector is only implied for other simple selectors and pseudo-elements when used without a namespace (this is why selectors like .foo
, #target
, [type="text"]
, :first-child
and ::before
are valid, and generally used with languages like HTML where CSS is most commonly used for styling). From the spec:
If a universal selector represented by *
(i.e. without a namespace prefix) is not the only component of a sequence of simple selectors selectors or is immediately followed by a pseudo-element, then the *
may be omitted and the universal selector's presence implied.
Therefore, in your example, the selector is invalid because there's neither a universal selector or a type selector between the |
and the :
:
/* These are all invalid */
*|:first-child
ns|::first-letter
|::before
If you specify a namespace, you must specify the universal selector if you don't select a specific type instead:
*|*:first-child
*|*::before
The same goes when selecting elements in an ns
namespace:
ns|*:first-child
ns|*::before
Or when selecting elements that are not in a namespace:
|*:first-child
|*::before