Arrows, dotted lines and dashes are extremely useful for diagrams and illustrations in SVG. Tools like Adobe Illustrator and Inkscape can add these decorations, but it’s useful to know how to add and adjust them manually. In this article, I’ll concentrate on strokes:
Basic Attributes
The appearance of a path is controlled with stroke
(the color of the path, defined using any CSS color system) and stroke-thickness
(assumed to measure pixels, although any CSS measurement system supported by SVG can be used).
Dashes
Strokes are provided with a dashes via the stroke-dasharray
attribute. Values are applied in the order of dash
and gap
; unitless numbers are assumed to be pixels, although the values could be specified in any units SVG understands (most commonly, percentages). Single values are assumed to be the same value for both dash and gap:
Given a line:
<svg viewBox="0 0 300 10">
<line x1="0" y1="0" x2="300" y2="0"
stroke="black" stroke-width="10" stroke-dasharray="5" />
</svg>
Which creates:
Those presentation attributes and values can be expressed in CSS to achieve the same result:
<svg viewBox="0 0 300 10">
<defs>
<style>
line#es {
stroke: black;
stroke-width: 5;
stroke-dasharray: 5;
}
</style>
</defs>
<line id="es" x1="0" y1="0" x2="300" y2="0" />
</svg>
If there are pairs of numbers for stroke-dasharray
, the second number in each pair denotes the gap:
line {
stroke: black;
stroke-width: 5;
stroke-dasharray: 5, 20;
}
If the attribute value count is odd, the values are repeated to make them even, so 5, 20, 5
renders as:
“Read” from left to right on the line above, these stroke-dasharray
values would be described as: “dash of 5, space of 20, dash of 5; space of 5, dash of 20, space of 5”.
stroke-dashoffset
The stroke-dashoffset
presentation attribute determines where the stroke starts; with a dash offset, it pushes the start “further into” the line:
line#dashstart {
stroke: black;
stroke-width: 5;
stroke-dasharray: 5, 20, 5;
stroke-dashoffset: 20;
}
Animating Strokes
It’s also possible to animate SVG stroke in CSS. If the stroke-dashoffset
has the same value as stroke-dasharray
and the length of the path itself; the stroke is essentially “pushed off” the visible end of the path. We can then animate this by changing stroke-dashoffset
to 0 over time:
@keyframes strokeanim {
to { stroke-dashoffset: 0; }
}
line#dashstart {
stroke: hsl(260, 50%, 30%);
stroke-width: 15;
stroke-dasharray: 300;
stroke-dashoffset: 300;
animation: strokeanim 2s alternate infinite;
}
Which produces:
The difficult part of this is usually determining the exact length of the path, and therefore the correct values for stroke-dasharray
and stroke-dashoffset
, which why it’s usually accomplished with JavaScript… which I’ll cover in an upcoming article.
Other Uses of Stroke
While this article has used lines for stroke examples for the sake of clarity and simplicity, strokes can be applied to any SVG basic shape, including polygons, polylines and paths. For example, it’s very easy to recreate visual effect of Adobe PhotoShop’s marquee selection tool with a <rect>
element and the CSS we have learnt so far:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200">
<style type="text/css">
rect#strokedrect {
stroke: hsl(260, 50%, 3%);
fill: white;
stroke-width: 7;
stroke-dasharray: 10;
}
</style>
<rect id="strokedrect" x="0" y="0" width="300" height="200" />
</svg>
Which creates:
Note that strokes are always drawn in the “mid-point” of the assumed path. In the examples so far, this hasn’t been an issue, as the elements were always the same size as their viewBox containers, and/or have a “transparent” fill. However, it can be a very real problem if either of these conditions is not true. For example, if the rectangle is drawn slightly inside the viewBox and given a colored fill:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200">
<style type="text/css">
rect#oddstrokedrect {
stroke: hsl(260, 50%, 3%);
fill: grey;
stroke-width: 12;
stroke-dasharray: 15;
}
</style>
<rect id="oddstrokedrect" x="20" y="20" width="260" height="160" />
</svg>
Which creates:
It’s entirely possible to animate this stroke as well:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200">
<style type="text/css">
@keyframes marchingants {
to { stroke-dashoffset: 19; }
}
rect#strokedrect {
stroke: hsl(260, 50%, 90%);
fill: white;
stroke-width: 7;
stroke-dasharray: 10;
animation: marchingants 1s forwards infinite linear;
}
</style>
<rect id="strokedrect" x="0" y="0" width="300" height="200" />
</svg>
Creating:
Conclusion
There are many more possibilities for advanced uses of SVG stroke and markers, as hinted in the introduction, which I’ll be looking at in the next article.
Photograph by Chris Searle, licensed under Creative Commons
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.