SVG Part 1 - Open standard for vector graphics
Tags: svg, graphics
Published: 2022-12-11 18:49:00

> 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oly91r5rpheu20zcvdqj.png)

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](https://caniuse.com/svg).

Many graphic vector editors support SVG, at least as an export format. In the open source world, [Inkscape](https://inkscape.org) 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
<?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>
```

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).
 
```xml
<rect 
 x="30" 
 y="30" 
 width="150" 
 height="100" 
 style="fill:blue; stroke-width:1; stroke:black"/>
```
![Rectangle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrkjefkk1gqurgsrxah1.png)

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

{% codepen https://codepen.io/raphiki/pen/Yzvbzmd %}

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

```xml
<circle 
 cx="70" 
 cy="70" 
 r="40" 
 stroke="black" 
 stroke-width="2" 
 fill="red"/>
```
![Circle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xrhd5hx0xq788cnyylyy.png)

```xml
<ellipse 
 cx="100" 
 cy="60" 
 rx="50" 
 ry="30" 
 style="fill:green; stroke-width:2; stroke:black"/>
```
![Ellipse](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vn5k2zrntk3kb3z37iny.png)

```xml
<line 
 x1="30" 
 y1="30" 
 x2="120" 
 y2="70" 
 style="stroke:black; stroke-width:2"/>
```
![Line](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8bsiemenl3rzbzxw2u3.png)

```xml
<polygon 
 points="120,70 100,30 170,50 30,50 70,90" 
 style="fill:pink; stroke:black; stroke-width:1"/>
```
![Polygon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v22gslvs2a1m8ycjqolf.png)

```xml
<polyline 
 points="30,30 60,30 30,60 60,60" 
 style="fill:white; stroke:red; stroke-width:2"/>
```
![Polyline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmlwnc6mnhg1omfqv0pe.png)

## 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).

```xml
<path 
 d="M100 100 L200 100 C150 50 125 125 100 150 Z"
 style="fill:green; stroke-width:2; stroke:blue"/>
```
![Path](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvgy5jpouf0u86064zft.png)

Let's explain the d attribute:
![Details of a path](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvbcbwi7ydosj62tcr53.png)

- 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktmp098sg7h96fdlzgt1.png)

Display Tux in your browser by directly accessing the [SVG file](https://upload.wikimedia.org/wikipedia/commons/3/35/Tux.svg).

## 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.

```xml
<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>
```
![Ref](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u11t84c98f55xsjr5j15.png)

## 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*.

```xml
<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>
```

Check it on Codepen:
{% codepen https://codepen.io/raphiki/pen/poKmVpP %}

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

```xml
<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"/>
```
![Linear gradient](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aue4lh4nwzeqdbziklb0.png)

```xml
<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"/>
```
![Radial gradient](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pfu2wh6n6o01hqw4yrbi.png)

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* 

```xml
<text 
 x="55" 
 y="90" 
 style="fill:red;font-size:18">
  SVG rocks!
</text>
```
![Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4vv14tsgcnf4ydd52rl1.png)

```xml
<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>
```
![Text with tspan](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rd2ekfl4o53b88cl6znp.png)

```xml
<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>
```
![Text on a path](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5mjatsdwe85mzbehqf0.png)

## 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.

```xml
<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"/>
```
![Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8l38666oznetod8shtug.png)

## 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)

```xml
<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"/>
```
![Inline CSS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ta5jxza4juq63jurouy.png)

```xml
<?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>
```

With myCss.css
```css
.myStyle {   
  fill:blue;    
  stroke-width:1;
  stroke:black
}
```
![External CSS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwpp0y2wbydumhd8pzh4.png)

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uz6fsizfk7n2q1k044tj.png)

```xml
<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>
```
![Translate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvsz18ptri9r3kh4bgmf.png)

```xml
<g transform="translate(30,30),scale(2)">
  <use xlink:href="#myGraph"/>
  <text>Scale(2)</text>
</g>
```
![Scale](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nzwprzuo6dtokv5htd73.png)

```xml
<g transform="translate(30,30),rotate(30)">
  <use xlink:href="#myGraph"/>
  <text>Rotate(30)</text>
</g>
```
![Rotate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fh4npk7ci5axzbks4kdo.png)

```xml
<g transform="translate(30,30),skewY(30)">
  <use xlink:href="#myGraph"/>
  <text>skewY(30)</text>
</g>
```
![Skew](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sqmqv2p7g5ja3jacr7pu.png)

```xml
<g transform="matrix(1.5 0.45 0.2 1 30 30)">
  <use xlink:href="#myGraph"/>
  <text>matrix</text>
</g>
```
![Matrix](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d43nl3hslc1o3o7lq9om.png)

## 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.