Can a CSS pseudo-class be namespaced?

2019-04-11 18:55发布

问题:

When using namespaces in CSS, you can select, for example, any div element in "any or no namespace" by using a namespaced type selector:

*|div

Is it valid CSS to namespace a pseudo-class? For example:

*|:first-child

It seems to work in WebKit based browsers, and it seems to not work in IE9 (below IE9 does not support namespaces at all) and Firefox. I don't care what browsers it does/doesn't work in, I just need to know whether it is a valid construct.

Here's a fiddle.

From what I can make out in the CSS grammar, it is not valid. But I may be misreading the grammar.

回答1:

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