I have been learning SVG and came across this informative article. The author states that
Most CSS selectors can be used to select SVG elements. In addition to the general type, class and ID selectors, SVGs can be styled using CSS2’s dynamic pseudo-classes (:hover, :active and :focus) and pseudo-classes (:first-child, :visited, :link and :lang. The remaining CSS2 pseudo-classes, including those having to do with generated content (such as ::before and ::after), are not part of the SVG language definition and, hence, have no effect on the style of SVGs.
This author has many articles on the web and appears very knowledgeable. However, the statement "the remaining CSS2 pseudo-classes....have no effect on the style of SVGs" makes one wonder about CSS3 pseudoclasses. Take this example I generated on Codepen (FF as browser).
<svg width="220" height="220" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="100" />
<rect x="110" y="110" width="100" height="100" />
</svg>
<style>
svg { border: 3px dashed #999 }
svg > rect:hover { fill: green }
rect:nth-child(even) { fill:red }
</style>
The CSS3 :nth-child pseudoclass works perfectly fine here (fills the 2nd rectangle red). Another example: substitute the :nth-child rule above with another CSS3 pseudoclass selector, a :not rule (all else remains the same):
rect:not([x="110"]) { fill:red } // fills the 1st rectangle red
I have found this reference but it does not help me.
What is the compatibility of CSS3 pseudoclasses with SVG elements?
Note: I am assuming these pseudoclass rules would only apply to SVG renderable elements.
Most CSS selectors can be used to select SVG elements. In addition to the general type, class and ID selectors, SVGs can be styled using CSS2's dynamic pseudo-classes (:hover, :active and :focus) and pseudo-classes (:first-child, :visited, :link and :lang.
Pseudo-classes enable you to target an element when it's in a particular state, as if you had added a class for that state to the DOM. Pseudo-elements act as if you had added a whole new element to the DOM, and enable you to style that.
Adding multiple pseudo elementsYou can combine several CSS pseudo-elements for one element. However, you cannot use CSS ::after two times or ::before two times. In the example below, the first letter of <div> is green and has x-large font size. The first line of <div> element is red and has small capital letters.
If you're talking about pseudo-classes, then yes, you can combine them in any order.
The following are the full list of CSS3 Pseudo-class Selectors as defined in Selectors Level 3 Editor's Draft, where the ones with bolded links
ones are compatible with SVG:
:target
, selects elements that are targeted via fragment identifiers:root
, selects the root of the document, which is the html
tag, with higher specificity
:nth-child(an+b)
, selects element that has an+b-1
siblings before it in the document tree:nth-of-type(an+b)
, selects element that has an+b-1
siblings before it with the same element name in the document tree:nth-last-of-type(an+b)
, selects element that has an+b-1
siblings after it with the same element name in the document tree:last-child
, selects any element that is the last child of its parent:first-of-type
, selects the first sibling of its type of the parent's children:last-of-type
, selects the last sibling of its type of the parent's children:only-child
, selects element that has a parent element that has no other children:only-of-type
, selects element that has a parent element that has no other children with the same element name:empty
, selects element that has no children at all:not(X)
, selects element that is not selected by selector X
, which is a simple selector
These were defined but without semantic meaning in the draft:
:enabled
:disabled
:checked
:indeterminate
The above are given meaning in the HTML5 Specification, along with a few other definitions for other pseudo-classes.
In summary, it seems like all CSS3 pseudo-classes work except for :root
. You can read more at the MDN documentation for pseudo-classes. I could not find a credible resource describing the compatibility, so this was all determined through testing. There are no other pseudo-classes or pseudo-elements defined in CSS3.
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.:empty
gets applied to all void svg elements, (<rect>
, <circle>
, <ellipse>
, <polygon>
, etc), it's a handy selector for targeting SVG shape elements.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With