Scalable Vector Graphics: Drawing Basics

In my previous posts we discussed what SVGs are and reasons you should consider SVGs for your project. In this article we’ll look at the basic concepts, document structure and drawing elements.

SVG Co-ordinate Space

An SVG is defined in whatever co-ordinate space you give it. That space does not necessarily relate to pixels, cm, inches or other units because the images are scalable to any dimension.

Optionally, you can define a viewbox which determines the co-ordinates your SVG uses. The following SVGs would look identical:

  • An SVG with a viewbox of 0,0 to 200,100 with a line from 0,0 to 100,50.
  • An SVG with a viewbox of 0,0 to 300,150 with a line from 0,0 to 150,75.

SVG drawing space

Your images are rendered within a viewport, i.e. the whole browser window or a block in an HTML page. By default, an SVG viewbox will stretch in either direction to fill the viewport space. However, you can state that you want the aspect ratio preserved.

Unlike mathematical graphs, the SVG co-ordinate system starts at the top left (usually 0,0) with the x-axis pointing right and y-axis pointing down. Therefore, a point at 100,200 represents 100 units to the right of the left hand edge and 200 units down from the top edge.

SVG Length Units

Lengths in SVG can be specified either as:

  • a relative value in the SVG space, e.g. 10
  • an absolute or relative measurement, e.g. 10px. SVG supports em, ex, px, pt, pc, cm, mm, in and percentage units.

If your image will be scaled, use units which are relative to your viewbox, e.g. a line width of 10 within a 100×100 viewbox will be 10% of the full width/height.

SVG XML Document

An SVG image is defined as an XML document. Assuming you’re creating a new SVG file, such as image.svg, an XML declaration and doctype must appear at the top of the document:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

This is followed by the root SVG element:


<svg xmlns="http://www.w3.org/2000/svg">

Several optional attributes can be applied to the svg element. Two important ones are:

  • viewBox: establish the dimensions — a rectangular co-ordinate area used for your image specified as “min-X min-Y width and height”, e.g. viewBox="0 0 600 400". It’s important to remember this is an abstract space; it does not relate to pixels and your drawing elements are not constrained within these co-ordinates.
  • preserveAspectRatio: defines how a viewbox is scaled. There are many options, for example preserveAspectRatio="xMidYMid meet" ensures the middle of an SVG’s viewbox is aligned with the middle of the viewport (the browser window or HTML element containing the SVG) and the image fits the space available while preserving its aspect ratio.

An optional title and description can be defined using title and desc elements. Our basic XML document is therefore:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 400" preserveAspectRatio="xMidYMid meet">
	<title>My First Scalable Vector Graphic</title>
	<desc>An experimental SVG from SitePoint.com</desc>

	<!-- drawing elements to go here -->

</svg>

Grouping Elements

Any set of elements (lines, circles, rectangles, text, etc.) can be grouped using <g> … </g> tags. In essence, it’s identical to grouping drawing objects in a graphics package so they can be manipulated as a single item.

Personally, I prefer to define a root group node so I can modify the whole image easily via JavaScript or CSS, e.g.


<g id="main">
	<!-- drawing elements to go here -->
</g>

A single group can have any number of nested inner groups.

Lines

A single line between two points is drawn using the line element:


<line x1="10" y1="10" x2="100" y2="200" 
stroke="#999" stroke-width="5" stroke-linecap="round" />

The stroke-linecap attribute defines the line-end effect and accepts values of butt (the default), round, square or inherit:

SVG stroke-linecap

Polylines

Polylines define a set of connected straight line segments:


<polyline points="580,10 560,390 540,200 520,390 400,390" 
stroke="#c00" stroke-width="5" stroke-linecap="round" 
stroke-linejoin="round" fill="none" />

The stroke-linejoin attribute defines the line-joining effect and accepts values of miter (the default), round, bevel or inherit:

SVG stroke-linejoin

Polygons

Polygons are are similar to polylines except that the resulting shape will always be closed:


<polygon points="350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" 
stroke="#ff0" stroke-width="10" fill="#ff6" />

Rectangles

Square or rounded rectangles are defined using the rect element:


<rect x="100" y="10" width="150" height="100" rx="10" ry="20" 
stroke="#060" stroke-width="8" fill="#0f0" />

The x and y attributes define the top-left corner. rx and ry specify the horizontal and vertical corner rounding.

Circles

Circles are defined using a center point and radius:


<circle cx="100" cy="300" r="80" 
stroke="#909" stroke-width="10" fill="#f6f" />

Ellipses

Ellipses are defined using a center point and two radii values:


<ellipse cx="450" cy="50" rx="80" ry="30" 
stroke="#0cc" stroke-width="10" fill="#0ff" />

Text

Basic text can be added using the text element:


<text x="240" y="390" font-family="sans-serif" font-size="50" fill="#00f">SVG</text>

The x and y attributes define the bottom-left co-ordinate of the first character in the string.

The Result

Our final SVG document contains the following XML code:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 400" preserveAspectRatio="xMidYMid meet">
	<title>My First Scalable Vector Graphic</title>
	<desc>An experimental SVG from SitePoint.com</desc>
	<g id="main">
		<line x1="10" y1="10" x2="100" y2="200" stroke="#00c" stroke-width="5" stroke-linecap="round" />
		
		<polyline points="580,10 560,390 540,200 520,390 400,390" stroke="#c00" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" fill="none" />
		
		<polygon points="350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" stroke="#ff0" stroke-width="10" fill="#ffc" />
		
		<rect x="100" y="10" width="150" height="100" rx="10" ry="20" stroke="#060" stroke-width="8" fill="#0f0" />
		
		<circle cx="100" cy="300" r="80" stroke="#909" stroke-width="10" fill="#f6f" />
		
		<ellipse cx="450" cy="50" rx="80" ry="30" stroke="#0cc" stroke-width="10" fill="#0ff" />
		
		<text x="240" y="390" font-family="sans-serif" font-size="50" fill="#00f">SVG</text>
	</g>
</svg>

and renders this image:


SVG example

click to view the actual SVG

While this is a simple example, the file is 1,176 bytes before minification and gzipping. The equivalent compressed PNG above is 5,611 bytes — it’s almost 5x larger and cannot be scaled above its native 407×274 resolution without losing quality.

Further Scalable Vector Graphic articles will appear on SitePoint soon…

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • Bhazo

    That is a lot of code to build a box…Flash was easier

    • http://www.optimalworks.net/ Craig Buckler

      Don’t worry – there are ways to reduce it which will be covered on SitePoint soon. Remember also that you don’t need to write the code — use a graphics app.

      • http://www.linkedin.com/profile/view?id=14898459 Grant Parks

        Have even more fun by using XSL to transform XML data directly to SVG :)

  • http://www.microstockman.com Microstock Man

    SVG’s are gaining a lot of notoriety, especially with free programs like inkscape making them available to people who don’t want to fork out on illustrator.

    Didn’t realise they were essentially an xml document! I have submitted a few as microstock lately, plus just wrote an article about selling vector graphics online at http://www.microstockman.com/selling-vector-graphic-designs-online/

    • http://www.linkedin.com/profile/view?id=14898459 Grant Parks

      It’s amazing that it’s taken as long as it has. I used SVG in 2002 or 3 to replace someone’s expensive 3rd party app. It was fun to change the SQL Server queries to return XML and XSL that directly into interactive charts and graphs. I love removing extra components in favor of Web standards — and getting rid of code, if you look at XSLT as XML data.

  • Eddie

    But Flash is not ubiquitous, it isn’t avail on some versions of Android and SVG is.

  • http://gregpettit.ca Greg

    Pretty nifty actually. Didn’t realize it was that easy. Could prove helpful if I ever need to build a graphing library instead of using one of the existing ones!

    What’s SVG support like? I have to admit, I’m not sure when I would use Canvas vs. when I would use SVG (and if they’re essentially the same thing) or what the differences in syntax would be. Will future articles cover this, too?

    Looking forward to what comes next.

    • http://www.optimalworks.net/ Craig Buckler

      To answer your questions, visit the article links in the first sentence.
      Every browser with native canvas support also supports SVG.

  • http://www.apple.com Jimmy Appletree

    Are SVG graphics compatible on all devices and browsers including mobile devices and apple products?

    • http://www.optimalworks.net/ Craig Buckler

      No. They won’t work in Lynx running on Windows 3.1.

      Basically, all modern browsers (IE9+, Android 3+) support SVGs. IE6/7/8 is your biggest stumbling block and, even then, you can use a shim.