Attributes inheritance
SVG is all about simplifying the life of an author who writes SVG by hand. One of such features is attributes inheritance.
Instead of writing:
<rect fill="green"/>
<rect fill="green"/>
we can write
<g fill="green">
<rect/>
<rect/>
</g>
and both rectangles will inherit the fill
attribute value.
As expected, this simple idea leads to death by a thousand cuts.
First, not all properties/attributes are inheritable.
For example, fill-opacity
is inheritable, but opacity
isn't.
You can find the whole list here
(see the Inh. column).
Second, for some reason, inheritance can be stated explicitly, like this:
<g fill="green">
<rect fill="inherit"/>
<rect/>
</g>
This would produce the same output as before, but makes parsing harder.
Third, some non-inheritable properties can be inherited explicitly
via the inherit
keyword, but only from the direct parent element.
For example:
<g opacity="0.5">
<rect/> <!-- opacity=1 -->
<rect opacity='inherit'/> <!-- opacity=0.5, effectively 0.25 -->
<g> <!-- opacity=1 -->
<rect opacity='inherit'/> <!-- opacity=1, effectively 0.5 -->
</g>
<g opacity='inherit'> <!-- opacity=0.5, effectively 0.25 -->
<rect opacity='inherit'/> <!-- opacity=0.5, effectively 0.125 -->
</g>
</g>
Fourth, when the inherit
keyword is used, but no parent element had defined this property,
the default value should be used.
All of this can lead to some bizarre and unexpected cases like:
<g stop-color="red">
<linearGradient id="lg1" stop-color="green">
<stop offset="0"/>
<stop offset="1" stop-color="inherit"/>
</linearGradient>
</g>
Here, the first stop would be black (default value, because stop-color
is non-inheritable)
and the second stop would be green (explicitly inherited from the parent).
And the stop-color
on g
has no effect, because it's non-inheritable.