What's the Difference Between CSS3's :Root Pseudo Class and HTML

What's the difference between CSS3's :root pseudo class and html?

From the W3C wiki:

The :root pseudo-class represents an element that is the root of the document. In HTML, this is always the HTML element.

CSS is a general purpose styling language. It can be used with other document types, not only with HTML, it can be used with SVG for example.

From the specification (emphasis mine):

This specification defines Cascading Style Sheets, level 2 revision 1 (CSS 2.1). CSS 2.1 is a style sheet language that allows authors and users to attach style (e.g., fonts and spacing) to structured documents (e.g., HTML documents and XML applications).

Is :root really useless?

For the vast majority of authors working with HTML, there are only two practical differences between :root and html:

  1. :root, being a pseudo-class, is more specific. If you require the lesser specificity of a type selector, it's entirely acceptable to use html instead of :root.
  2. :root can be used to hide rules from Internet Explorer 8 and older (a use case that perhaps isn't prevalent in 2017 but was fairly common half a decade ago).

Other than that, the :root pseudo-class is indeed designed primarily for the use case of matching the root element in an arbitrary document without having to know the type of element, which means XML-based languages and even other, non-XML-based types of documents. Remember that as of level 3, the Selectors module is designed for a variety of uses with a variety of document languages, and not just styling HTML elements with CSS (which is why it's now simply called "Selectors" and not "CSS Selectors", despite it being a CSS module).

Additionally, for host languages where the root element doesn't have its own type (e.g. in a language where element may be both the root element, and nested), :root is necessary for distinguishing the root element from nested elements (though alternatives exist, like :not(:nth-child(n)) with equal specificity in Selectors 3, or :not(* > *) with zero specificity in Selectors 4).

What is the css / html `root` element?

There is no element called root in HTML. The html element itself is "the root element" (which is the term given to the element which is the ancestor of all the other elements in the document), but this would be matched by html { }.

However, see the :root pseudo-class (with a colon).

What is the difference between pseudo-classes and pseudo-elements?

From https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Pseudo-classes_and_pseudo-elements

Pseudo-class :

A CSS pseudo-class is a keyword, preceded by a colon (:), added to the end of selectors to specify you want to style the selected elements, and only when they are in certain state. For example, you might want to style an element only when it is being hovered over by the mouse pointer, or a checkbox when it is disabled or checked, or an element that is the first child of its parent in the DOM tree.

Examples:

  • :active
  • :checked
  • :nth-child()
  • :first
  • :hover

Pseudo-elements ::

Pseudo-elements are very much like pseudo-classes, but they have differences. They are keywords, this time preceded by two colons (::), that can be added to the end of selectors to select a certain part of an element.

Examples:

  • ::after
  • ::before
  • ::first-letter
  • ::first-line
  • ::selection
  • ::backdrop

As stated by @stephanmg:

In practice ::before is used as :before and ::after is used as :after
because of browser compatibility. Both are pseudo-elements, but may
look like pseudo classes. This might be confusing if you read CSS
code.

What is the difference between :before and ::before?

This distinguishes pseudo elements from pseudo classes.

The difference between pseudo classes and pseudo elements is described at http://www.d.umn.edu/~lcarlson/csswork/selectors/pseudo_dif.html

What's the :any-link pseudo-class for?

:any-link is a new pseudo-class proposed in Selectors level 4, that matches all elements that would be matched by :link, :visited. From what I see, its main purpose is to simplify selectors that need to select any hyperlinks, since the naming of :link is misleading; it specifically means unvisited links only, rather than all hyperlinks (which makes it essentially the opposite of :visited).

For the purposes of :link and :visited, WHATWG HTML and W3C HTML5 both define a "hyperlink" as any one of:

  • An <a> element that has an href attribute. This excludes named anchors (that is, <a> elements without an href attribute but instead with a name attribute), which were used traditionally to mark anchors in a page, now superseded by the use of an id attribute on any element. See named anchors in HTML 4.

  • An <area> element that has an href attribute.

  • A <link> element that has an href attribute.

For example, consider a scenario where links in the page header should be colored differently from all other links:

body > header > a:link, body > header > a:visited {
color: white;
}

Notice the body > header part is duplicated across both selectors. This seems redundant, but is currently necessary in order to color links in the page header differently from the rest, but regardless of their visited state. This is because body > header > a is not specific enough which requires using !important to override anyway, and body > header > a:link troublesomely only applies to unvisited links.

With the :any-link pseudo-class, you can simply do this instead:

body > header > a:any-link {
color: white;
}

Specificity is exactly the same as with each individual half, so there should be no issues there.

Of course, since no browser implements it unprefixed yet, that won't work. As an alternative, considering you're most likely working with an HTML document anyway you can just use a[href] instead, which works in all browsers including IE7+ on top of also being equally specific:

body > header > a[href] {
color: white;
}

There's a much more elaborate explanation regarding the use of a versus a:link, a:visited versus a:any-link versus a[href] in this other answer of mine.

Like anything else that has a prefix in CSS, :-moz-any-link and :-webkit-any-link exist only for experimental purposes, so you shouldn't use them with your sites. Besides, even if you were to use them right now, you'd have to duplicate the rules themselves (and not just the selectors!) since browsers have to drop entire rules on unrecognized selectors, rendering them pretty useless in real-world code!

As of early 2013, no other implementations of :any-link exist that I know of. I'm unsure as well as to whether this was implemented by the respective vendors and then proposed for inclusion in Selectors 4, or if it was preliminarily specced before the vendors began implementing it, but I don't think that matters.

Speaking of which, be sure not to confuse the :-moz-any-link/:-webkit-any-link pseudo-class with :-moz-any()/:-webkit-any(), the latter of which is specced as :matches() instead (possibly to avoid naming confusion?).

What is the compatibility of CSS3 pseudoclasses with SVG renderable elements?

Here's a pen that demonstrates the application of the full list of CSS3 Pseudo-class Selectors (outlined by @andrewli) on SVGs by applying fill or stroke attributes to SVG renderable elements.

I defined the different SVG elements in two different groups (two parent elements, shown in the pen as two columns) in order to fit in all the pseudo-classes that select different kinds of children:

<svg width="450" height="300">
<g transform="translate(5,5)">
<rect x="0" y="0" width="25" height="25" />
<rect x="0" y="40" width="25" height="25" />
<rect x="0" y="80" width="25" height="25" />
<circle cx="15" cy="132" r="13.5"/>
<circle cx="15" cy="170" r="13.5"/>
<polygon points="2,200 28,200 14,225"/>
<rect x="0" y="240" width="25" height="25" />
</g>
<g transform="translate(5,5)">
<rect x="220" y="0" width="25" height="25" />
</g>
<g transform="translate(5,5)" font-family="Verdana" font-size="16" fill="#444">
<text x="40" y="20" >:root</text>
<text x="40" y="60">:nth-child(2)</text>
<text x="40" y="100">:nth-of-type(3)</text>
<text x="40" y="140">:first-of-type</text>
<text x="40" y="180">:nth-last-of-type(1)</text>
<text x="40" y="220">:only-of-type, :last-of-type</text>
<text x="40" y="260">:nth-last-child(1), :last-child</text>
<text x="260" y="20">:only-child, :last-child</text>
</g>
</svg>

Interesting findings:

  • :root does appear to work. As expected, it gets applied to all elements, including svg elements, in the document.
  • Since :empty gets applied to all void svg elements, (<rect>, <circle>, <ellipse>, <polygon>, etc), it's a handy selector for targeting SVG shape elements.


Related Topics



Leave a reply



Submit