SVG Support
SVG elements are supported for usage as background-image
and as source for <img>
nodes. Starting with version 1.15 inline SVGs are available as well.
The feature set that is supported is a large subset of the SVG Tiny 1.2 specification. SVG elements can be styled and animated, using standard CSS.
The most notable sections from the specification that are missing are:
- 10 Text
- Basic support for
<text>
nodes. No other properties/nodes are supported. <tspan>
nodes are ignored and the text in them is a part of the parent<text>
node.
- Basic support for
- 12 Multimedia
- No multimedia support.
- 13 Interactivity
- No interactivity support.
- 14 Linking
- Support for
xlink:href
attribute in<use>
elements; The newer versionhref
is not supported.
- Support for
- 15 Scripting
- No support for
<handler>
, or<listener>
elements.
- No support for
- 16 Animation
- No SMIL animation support. CSS/web animations can be used instead.
- 17 Fonts
- No support for SVG fonts.
- 18 Metadata
- No support for metadata.
- 19 Extensibility
- No extensibility support (i.e. no
<foreignObject>
elements).
- No extensibility support (i.e. no
SVG elements support
Element type | Notes |
---|---|
<circle> | |
<defs> | |
<desc> | |
<ellipse> | |
<g> | |
<line> | |
<linearGradient> | |
<path> | |
<polygon> | |
<polyline> | |
<radialGradient> | |
<rect> | |
<solidcolor> | * Deprecated in the web standard, but supported. |
<stop> | |
<style> | |
<svg> | |
<text> | |
<title> | |
<use> | |
<mask> | * See the notes below |
* Gradients applied on use elements follow the color stops, as if defined in the coordinate space of the used element. | |
* Does not create Shadow DOM yet, uses alternative methods for displaying the linked node. |
Notes on the
<mask>
element support:
- SVG elements cannot have
mask=url(#...)
andclip-path=url(#...)
simultaneously,<mask>
elements do not support themask-type
property.<mask>
elements support only alpha masking mode (mask-type=alpha
)<mask>
elements support only the attributesx
,y
,width
,height
,maskContentUnits
, andmaskUnits
<mask>
elements must always have theirx
,y
,width
, andheight
specified. The default usage should be<mask id="maskId" x="0%" y="0%" width="100%" height="100%">...</mask>
SVG attributes support
Attributes | Notes |
---|---|
fill | |
fill-opacity | |
viewport-fill | |
viewport-fill-opacity | |
stroke-opacity | |
stroke-width | |
stroke-linecap | |
stroke-linejoin | |
stroke-miterlimit | |
stroke | |
xml:space | |
stop-opacity | |
stop-color | |
fill-rule | Parsed, but not used at this point. Only “even-odd” fill rule is supported. |
rx | |
ry | |
x | |
y | |
x1 | |
y1 | |
x2 | |
y2 | |
cx | |
cy | |
r | |
points | |
preserveaspectratio | |
viewbox | |
xlink:href | No support for the newer href |
gradientunits | |
offset | |
solid-opacity | |
solid-color | |
stroke-dashoffset | |
stroke-dasharray | |
d | |
width | |
height | |
font-size | |
transform | |
style |
“Duplicated” SVG attributes / CSS properties
The following SVG attributes have the same name as standard CSS properties, but need to be parsed differently:
width
height
font-size
transform
The most notable difference is that you need to include measurement units (e.g. px
, em
, etc.) in CSS properties, while SVG attributes are unitless and it’s an error to specify the units. There are a few more differences in the transform
property, as it can define a transform-origin
in the SVG variant.
You don’t need to worry about defining CSS keyframe animations, except when using the “duplicated” properties. See the Animation section below for more details.
Using the inspector
- Node’s internal text cannot be changed through the inspector (attributes can be changed).
- Hovering elements within the
svg
element root won’t be highlighted.- This is due to the internal representation of SVG nodes (they do not exist in the Layout tree). Support for this is not planned at the moment.
Animation
Standard CSS animations are supported for animating inline SVGs.
There are two important shortcomings to note:
- Several CSS properties use the same name as SVG ones but are parsed differently. For example,
width
in standard CSS must include the units in which thewidth
is specified, while SVG’swidth
must not. Due to internal specifics, when defining keyframe animation for such “duplicated” properties, you must include the units, even though you shouldn’t by standard. Note how they
property (which is available for SVGs only) doesn’t have units specified, whilewidth
needspx
.
@keyframes moving-rect {
0% {
y: 0;
width: 85px;
}
100% {
y: 100;
width: 125px;
}
}
- Interpolating between 2 paths containing elliptical arc curves (
A
/a
commands) is not guaranteed to be interpolatable, even if they contain the same types of commands. This is because elliptical arcs are converted to up to 4 quadratic Bezier curves, leading to possible differences in the internal path representation. Paths that have the same types of internal commands are the only ones that can be interpolated. For example,M 10,30 A 20,20 0,0,1 50,30
cannot be interpolated withM 10,30 A 40,20 0,0,1 50,30
, because the first path’s arc is converted to 2 Bezier curves while the second is converted to a single one. If possible, avoid using elliptical arcs and use quadratic/cubic curves.
Performance optimizations
SVGs are internally cached when one of the following conditions is satisfied:
coh-use-aa-geometry
is disabled (default: enabled)- The content size of the SVG does not exceed 1024x1024, and in the case of a non-inline SVG element,
background-repeat
is not set tono-repeat
SVGs are re-tessellated and redrawn when one of the following conditions is satisfied:
- The content rectangle has changed (e.g., as a result of an animated element)
- The element has been invalidated because of a change in the style of an SVG node
Inline SVGs are never cached in GPU textures. They completely follow the redraw rules as the other DOM elements, in other words, they are redrawn only if a region of their content is dirty.
Example:
<!DOCTYPE html>
<html>
<style>
.cached1 {
width: 300px;
height: 300px;
background-image: url("cohtml.svg");
}
.cached2 {
width: 2048px;
height: 2048px;
background-image: url("cohtml.svg"); /* 800x600 content size */
}
.cahced3 {
width: 300px;
height: 300px;
}
.cahced4 {
width: 300px;
height: 300px;
background-repeat: no-repeat;
}
.non-cached1 {
width: 300px;
height: 300px;
background-image: url("cohtml.svg");
background-repeat: no-repeat;
}
.non-cached2 {
width: 300px;
height: 300px;
background-image: url("cohtml-large.svg"); /* 2048x2048 content size */
}
</style>
<body>
<!-- Cached, since the content rectangle of `cohtml.svg` does not exceed 1024x1024. The element size is irrelevant. -->
<div class="cached1"></div>
<div class="cached2"></div>
<!-- Inline images are also cached. The `background-repeat` property is ignored here. -->
<img class="cached3" src="cohtml.svg">
<img class="cached4" src="cohtml.svg">
<!-- Not cached, since the `background-repeat` property is set to `no-repeat`. -->
<div class="non-cached1"></div>
<!-- Not cached, since the content rectangle of `cohtml-large.svg` exceeds 1024x1024. The element size is irrelevant. -->
<div class="non-cached2"></div>
</body>
</html>