@svg
Creates an SVG image from XML or a CSS-like syntax.
The result is a url() for background, mask or border-image,
and an inline element when used with @content.
Syntax
- @svg(<svg-body>)
- @svg(<svg ...>...</svg>)
- svg-body
-
CSS-like rules. Top-level declarations become attributes of the
<svg>root; blocks become its children. Wrapping the body insvg { }is optional. - XML
-
Used as written when the body starts with
<.xmlnsis added if it is missing.
A simple shape
Write an element as a block, with its attributes inside. Here, circle creates a
<circle>, and cx, cy: 5 sets both coordinates to 5.
Declarations outside the block belong to the SVG itself.
viewBox: 10 is short for viewBox: 0 0 10 10:
a coordinate area 10 units wide and 10 units high. Two numbers, such as
viewBox: 10 20, set the width and height separately.
@grid: 1 / 60vmin;
background: @svg(
viewBox: 10;
circle {
cx, cy: 5;
r: 4;
fill: #000;
}
); The same image as XML:
@grid: 1 / 60vmin;
background: @svg(
<svg viewBox="0 0 10 10">
<circle cx="5" cy="5" r="4" fill="#000"/>
</svg>
); Repeating elements
Add * after an element name to repeat it: circle*10 makes 10 circles.
Use @n for the current step, starting at 1. Like @m,
repetition also accepts a range (1-5) or a grid (16x16).
This grid uses @nx and @ny for each line’s coordinates,
and @p to pick its direction. The padding .2 on the viewBox
adds space around the edges so the strokes are not clipped.
@grid: 1 / 60vmin;
background: @svg(
viewBox: 0 0 16 16 padding .2;
stroke: #000;
stroke-width: .4;
stroke-linecap: round;
line*16x16 {
x1, y1, x2, y2: @p(
@nx(-1) @ny(-1) @nx @ny,
@nx @ny(-1) @nx(-1) @ny,
@nx @ny(-1) @nx @ny
);
}
);
Functions work inside @svg too. Here, each circle’s position, size, and color
depend on @n, forming a Fibonacci spiral.
@grid: 1 / 60vmin;
background: @svg(
viewBox: -50 -50 100 100;
circle*300 {
fill: hsl($(120-90*@sin.n), 80%, 50%);
r: @sqrt(@n/60);
cx: $(@n*.618^4 * cos(2π*@n*.618));
cy: $(@n*.618^4 * sin(2π*@n*.618));
}
); Gradients and definitions
A gradient can go directly in fill. It is placed in <defs>
and given an id; the fill becomes url(#id). There is no need to write either yourself.
@grid: 1 / 60vmin;
background: @svg(
viewBox: 0 0 10 10;
rect {
width, height: 10;
fill: linearGradient {
gradientTransform: rotate(45);
stop { offset: 0; stop-color: #000 }
stop { offset: 1; stop-color: #e6437d }
}
}
);
The same syntax works for patterns, filters, clip paths, masks, markers, and symbols.
An explicit defs is optional: fill: defs linearGradient { … }
works too. For href and xlink:href, the reference is #id
rather than url(#id).
For a shorter way to write gradients, see @linearGradient and @radialGradient.
Inline SVG
Use @content instead of background
to put the SVG element inside the cell, rather than use it as a background image.
@grid: 1 / 60vmin auto;
@content: @svg(
viewBox: -5 -5 10 10;
circle*12 {
r: @nN(*4);
fill: none;
stroke: #000;
stroke-width: .15;
}
); Animation
draw: 3s infinite draws a shape’s stroke over three seconds, then repeats.
Set a stroke to make it visible. This works on paths, lines, circles,
ellipses, rectangles, polygons, and polylines.
@grid: 1 / 60vmin;
background: @svg(
viewBox: 0 0 10 10 p 2;
path {
stroke: #000;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: .4;
fill: none;
draw: 3s infinite;
d: M 0 0
@M10.pn(0 @n @n 0, @n 0 0 @n)
@M10.pn(@n @N @N @n, @N @n @n @N);
}
);
To animate an attribute, write animate followed by its name.
Separate the values with semicolons, then put the timing after /.
These circles grow from a radius of 0.2 to 0.8 and shrink back over two seconds.
@grid: 1 / 60vmin;
background: @svg(
viewBox: -5 -5 10 10;
circle*8 {
cx, cy: @Plot(r: 3);
r: .6;
fill: #000;
animate r: .2; .8; .2 / 2s ease infinite;
}
);
Timing accepts a duration, an optional delay, a repeat count or infinite,
and an easing such as ease. For example, 2s 1s 3 waits one second,
then runs three times for two seconds each. Add forwards or freeze
to keep the final value. The same timing options work with draw.
A single animation value is the target value. Use animate transform for
an SVG transform animation. With no attribute name, animate is an alias for draw.
The viewBox padding also has a short form: p 2 means padding 2.
Other shortcuts
| Syntax | Meaning |
|---|---|
g { circle { … } } | A circle inside a group. g circle { … } and g > circle { … } do the same. |
circle, rect { … } | Two elements with the same attributes. |
x, y: 1, 2; | Sets x="1" and y="2". A single value sets both attributes. |
rect#a.b { … } | A rectangle with id="a" and class="b". |
content: hello; | Text inside the element, for example in a text block. |
style { circle { … } } | A stylesheet inside the SVG. Its contents are ordinary CSS. |
style fill: red; | An inline style. Use style: { … } for several CSS declarations. |
--r: 3; | A variable for use in $() expressions inside the SVG. |
Element and attribute names are case-insensitive in the CSS-like syntax:
viewbox works like viewBox.
To generate SVG markup as a string in JavaScript, use the svg() generator.