SVG Part 1 - Open standard for vector graphics

raphiki

raphiki

Posted on December 11, 2022

SVG Part 1 - Open standard for vector graphics

The objective of this first post is to present the SVG standard for static vector graphics. It will be completed by a second post regarding it's dynamic aspects.

The SVG standard

SVG stands for Scalable Vector Graphic, it is an XML language for describing two-dimensional vector drawings. It is an open standard and specification of the W3C whose version 1.0 dates back to 2001. The current version is 1.1 which was released in 2003. Work on the SVG 1.2 Full version is ongoing.

In terms of graphic formats we can differentiate between two main families, raster formats (PNG, JPEG...) and vector formats (SVG, EPS...). A vector format does not contain the image per se, but descriptive elements – or vectors – of that image, which a viewer will be able to use to construct the image described. In summary, a vector image will describe a line where a raster image will describe a set of points constituting a line.

The V of SVG indicates that it is a vector image. Since it is built on the fly by the viewer, it can therefore be enlarged (zoomed) without degradation of quality and printed at any resolution. On the other hand, raster formats are usually limited to a single resolution. The figure below illustrates the difference between vector and raster formats when zooming an image.

Figure 1: raster (SVG) and vector (PNG) images

In addition to that, SVG is not limited to this descriptive aspect, the specification also contains the definition of element animation, event-based scripting, and document editing.

SVG is a text-based, non-binary and open format that is highly compressible, indexable and can be edited from any text editor. Being XML-based, it is also compatible with other W3C specifications such as the Document Object Model (DOM) and CSS. It is today natively supported by all recent Web browsers.

Many graphic vector editors support SVG, at least as an export format. In the open source world, Inkscape is a well-known native SVG editor. Many frameworks and libraries are also available to generate and manage SVG documents from most programing languages.

The purpose of this post is not to present the declarative language of SVG exhaustively, but rather to provide an overview through examples.

Basic structure of a SVG document

The most common basic structure of an SVG document is as follows:

<?xml version="1.0" standalone="no"?>
<! DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
   "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
 xmlns="http://www.w3.org/2000/svg">
  <!-- SVG declarations -->
</svg>
Enter fullscreen mode Exit fullscreen mode

The first line indicates, via the standalone attribute, that the XML document refers to an external file, in this case the DTD file in the second line.

The svg tag defines the root of the document. Note the use of the SVG specific namespace: http://www.w3.org/2000/svg.

Elements described in an SVG document can also be grouped into new svg tags or g tags.

Coordinates, which can be absolute or relative, start at the top left of the coordinate system. Just like distances, they are expressible in several units of measurement: px (by default), cm/mm, pt, %... These are actually the same units as CSS.

Groups of objects (such as svg, g or symbol and defs described later) define new coordinate systems.

Simple geometric shapes

SVG can handle the following basic geometric shapes: rectangles, circles, ellipses, lines, polylines, polygons, and paths. Let's illustrate their use via examples (for the sake of readability we will omit the tags <? xml?>, <! DOCTYPE> and svg presented above).

<rect 
 x="30" 
 y="30" 
 width="150" 
 height="100" 
 style="fill:blue; stroke-width:1; stroke:black"/>
Enter fullscreen mode Exit fullscreen mode

Rectangle

If you want to play with this example use the Codepen below:

You can also inject the following examples by copying/pasting the SVG code and of course modify it.

<circle 
 cx="70" 
 cy="70" 
 r="40" 
 stroke="black" 
 stroke-width="2" 
 fill="red"/>
Enter fullscreen mode Exit fullscreen mode

Circle

<ellipse 
 cx="100" 
 cy="60" 
 rx="50" 
 ry="30" 
 style="fill:green; stroke-width:2; stroke:black"/>
Enter fullscreen mode Exit fullscreen mode

Ellipse

<line 
 x1="30" 
 y1="30" 
 x2="120" 
 y2="70" 
 style="stroke:black; stroke-width:2"/>
Enter fullscreen mode Exit fullscreen mode

Line

<polygon 
 points="120,70 100,30 170,50 30,50 70,90" 
 style="fill:pink; stroke:black; stroke-width:1"/>
Enter fullscreen mode Exit fullscreen mode

Polygon

<polyline 
 points="30,30 60,30 30,60 60,60" 
 style="fill:white; stroke:red; stroke-width:2"/>
Enter fullscreen mode Exit fullscreen mode

Polyline

Paths

SVG also allows you to declare geometric shapes as paths, to do this, several commands can be combined:

  • M: move to a given position
  • L: draw a line to a given position
  • H: draw an horizontal line to a given abscissa
  • V: draw a vertical line to a given ordinate
  • C and S: draw a cubic Bezier curve (with two control points)
  • Q and T: draw a quadratic Bezier curve (with a control point)
  • A: draw an elliptical arc
  • Z: finalize the path by drawing a straight line between the last point and the first point.

These controls can be used in absolute position (capital M, L, H, V, C, S, Q, T, A and Z) or in relative position (m, l, h, v, c, s, q, t, a and z).

<path 
 d="M100 100 L200 100 C150 50 125 125 100 150 Z"
 style="fill:green; stroke-width:2; stroke:blue"/>
Enter fullscreen mode Exit fullscreen mode

Path

Let's explain the d attribute:
Details of a path

  • Instruction 1: the cursor is positioned at point (100,100)
  • Instruction 2: a line is drawn from the cursor to the point (200,100)
  • Instruction 3: a Bezier curve is drawn to the point (100.150) by positioning the two control points in (150,50) and (125,125)
  • Instruction 4: the path is finalized via a line drawn between (100,150) and the starting point (100,100).

It is the use of complex paths that makes it possible to draw any shape. To convince yourself of this, open the Inkscape XML editor ("Edit / XML Editor" menu) or your favorite text editor on a complex drawing like Tux's...

Tux naked

Display Tux in your browser by directly accessing the SVG file.

Internal references and links

SVG allows you to reference reusable objects, previously defined with the defs or symbol tags. This is achieved thanks to the support of Xlink whose namespace must be added in the svg tag.

<svg width="100%" height="100%" version="1.1" 
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink= "http://www.w3.org/1999/xlink">
  <defs>
     <circle id="myCircle" 
      r="20" 
      stroke="blue" 
      stroke-width="2"/>   
  </defs>
  <use xlink:href="#myCircle" 
   x="100" 
   y="10" 
   fill="yellow"/>
  <use xlink:href="#myCircle" 
   x="150" 
   y="20" 
   fill="red"/>
</svg>
Enter fullscreen mode Exit fullscreen mode

Ref

External links

SVG allows you to link to external resources identified by URIs. This is used, for example, to create hyperlinks or reference style sheets. This is also achieved thanks to the support of Xlink.

<svg width="100%" height="100%" version="1.1" 
 xmlns="http://www.w3.org/2000/svg" 
 xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <a xlink:href="https://blog.worldline.tech" 
     target="_blank">
    <rect x="30" 
     y="30" 
     width="150" 
     height="100"
     style="fill:blue; stroke-width:1; stroke:black"/>
  </a>
</svg>
Enter fullscreen mode Exit fullscreen mode

Check it on Codepen:

Gradients

Color gradients can be used for filling elements. SVG handles both linear and radial gradients.

<defs>
  <linearGradient id="myGradient">
    <stop offset="5%" stop-color="blue" />
    <stop offset="95%" stop-color="red" />
  </linearGradient>
</defs>
<rect 
 fill="url(#myGradient)" 
 stroke="black" 
 stroke-width="3"
 x="50" 
 y="50" 
 width="100" 
 height="50"/>
Enter fullscreen mode Exit fullscreen mode

Linear gradient

<defs>
  <radialGradient id="myGradient" 
   gradientUnits="userSpaceOnUse" 
   cx="100" cy="75" 
   r="50" 
   fx="100" fy= "75">     
    <stop offset="0%" stop-color="red" />
    <stop offset="100%" stop-color="blue" />
  </radialGradient>
</defs>
<rect fill="url(#myGradient)" 
 stroke="black" 
 stroke-width="3"
 x="50" y="50" 
 width="100" height="50"/>
Enter fullscreen mode Exit fullscreen mode

Radial gradient

There are many additional attributes related to gradients, which are not discussed here for simplicity. In general, refer to the W3C standard for a detailed and exhaustive description of SVG elements and other attributes.

Text

In SVG, text is a graphic object like any other. By default it is displayed on one line, but it is also possible:

  • to separate it into several sections with the tspan tag
  • attach it to the outline of a path element with the textPath tag and an Xlink
<text 
 x="55" 
 y="90" 
 style="fill:red;font-size:18">
  SVG rocks!
</text>
Enter fullscreen mode Exit fullscreen mode

Text

<text 
 x="55" 
 y="90" 
 style="fill:red;font-size:18;">
  My new post:
  <tspan x="70" dy="20">Dynamic</tspan>
  <tspan x="70" dy="20" style="fill:blue;">Vector</tspan>
  <tspan x="70" dy="20">Drawing</tspan>
</text>
Enter fullscreen mode Exit fullscreen mode

Text with tspan

<defs>
  <path id="myPath" 
   d=" M 40 40 C 80 40 120 0 160 40 C 200 80 240 90 280 80"/>
</defs>
<use xlink:href="#myPath" 
 style="fill:none;  
 stroke:blue;"/>
<text style="fill:red;">
  <textPath xlink:href="#myPath">
    Let's go down the rabbit hole!
  </textPath>
</text>
Enter fullscreen mode Exit fullscreen mode

Text on a path

Images

It is possible to insert images into an SVG document, the supported formats are JPEG and PNG for raster formats and SVG itself for vector.

<rect 
 x="30" y="30" 
 width="110" height="110" 
 style="fill:blue; stroke-width:1; stroke:black"/>
<image 
 x="35" y="35" 
 width="100" height="100"
 xlink:href="SVG.png"/>
Enter fullscreen mode Exit fullscreen mode

Image

Styles and CSS

As you may have already noticed in previous examples, SVG allows you to assign styles to elements. Just like in X/HTML, this can be done in two different ways:

  • by using the style attribute that allows you to declare the style in the tag of the element itself
  • through the use of the class attribute, which allows you to reference a predefined style in an internal or external CSS style sheet (via a <?xml-stylesheet?> statement)
<style type="text/css">
  <! [CDATA[     
    . myStyle {
      fill:blue;
      stroke-width:1;
      stroke:black}
  ]]>
</style>
<rect 
 x="100" y="30" 
 width="60" height="40"
 style="fill:red; strokewidth:1; stroke:black"/>
<rect 
 x="30" y="30" 
 width="60" height="40" 
 class="myStyle"/>
Enter fullscreen mode Exit fullscreen mode

Inline CSS

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet href="myCss.css" type="text/css"?>
<! DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
 xmlns="http://www.w3.org/2000/svg">
  <rect 
   x="30" y="30" 
   width="60" height="40" 
   class="myStyle"/>
</svg>
Enter fullscreen mode Exit fullscreen mode

With myCss.css

.myStyle {   
  fill:blue;    
  stroke-width:1;
  stroke:black
}
Enter fullscreen mode Exit fullscreen mode

External CSS

Transformations

SVG has a system of transformations applicable to declared objects or groups of objects. These are actually mathematical transformations between coordinate systems. SVG provides the following transformations:

  • translate(x,y): translation of the element to the coordinates (x,y)
  • scale(Nx,Ny): scaling with the ratios Nx for abscissa and Ny for ordinates (default Nx=Ny)
  • rotate(deg,cx,cy): rotation of deg degrees, from the point (cx,cy) (by default origin of the current coordinate system)
  • skewX(deg) and skewY(deg): tilt on the x-axis or y-axis
  • matrix(a b c d e f): mathematical transformation of coordinates corresponding to the following matrix formula: Transformation matrix
<defs>
<g id="myGraph" fill="none" stroke="red" stroke-width="3">
  <line 
   x1="0" y1="0" 
   x2="50" y2="0" />
  <line 
   x1="0" y1="0" 
   x2="0" y2="50" />
</g>
</defs>
<g transform="translate(30,30)">
 <use xlink:href="#myGraph"/>
  <text>Translation</text>
</g>
Enter fullscreen mode Exit fullscreen mode

Translate

<g transform="translate(30,30),scale(2)">
  <use xlink:href="#myGraph"/>
  <text>Scale(2)</text>
</g>
Enter fullscreen mode Exit fullscreen mode

Scale

<g transform="translate(30,30),rotate(30)">
  <use xlink:href="#myGraph"/>
  <text>Rotate(30)</text>
</g>
Enter fullscreen mode Exit fullscreen mode

Rotate

<g transform="translate(30,30),skewY(30)">
  <use xlink:href="#myGraph"/>
  <text>skewY(30)</text>
</g>
Enter fullscreen mode Exit fullscreen mode

Skew

<g transform="matrix(1.5 0.45 0.2 1 30 30)">
  <use xlink:href="#myGraph"/>
  <text>matrix</text>
</g>
Enter fullscreen mode Exit fullscreen mode

Matrix

Conclusion

This post showed how to create simple SVG elements thanks to its rich and simple syntax.

This introduction to SVG is not intended to be exhaustive. Some elements were not addressed, such as patterns (reusable objects for filling), filters (such as Gaussian blurs for instance), markers (graphic objects used at the end of a path, for example an arrow at the end of a line), clipping, masking and composition techniques.

Stay tuned for our second post on Dynamic SVG.

💖 💪 🙅 🚩
raphiki
raphiki

Posted on December 11, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related