A quick(ish) guide to Scaleable Vector Graphics
What is an SVG?
A scaleable vector graphic, or an SVG as they are more commonly known, is a single/series of basic shape elements. In layman’s terms it’s a type of image format, like JPG, PNG and GIF. Designers will have worked with vector graphics at some point, most notably in Adobe Illustrator or Sketch. SVGs are exactly the same as your Illustrator/Sketch illustrations but written in XML for the web.
Why use an SVG?
There are many benefits for replacing the JPGs and PNGs on your website for SVGs:
- They are smaller in file size.
- SVGs can have transparent backgrounds like PNGs.
- It’s just as easy to save an illustration as an SVG as it is any other image format.
- Any text included in an SVG inside <text> tags is SEO friendly and, more importantly, accessible.
- As the name suggests, they are scaleable. you can make them as big or as little as you want without losing quality. Imagine that!
But I’ve been using other image formats without any problems, why should I use SVGs now?
It has never been a better time to embrace SVGs! Web page loading times are increasingly important, and to keep those users coming back to your site your content needs to load in the smallest possible time. Mere milliseconds. You can test your website’s performance by using Google’s PageSpeed tool.
SVGs can help reduce the size of your web page. Replace all JPG/PNG vector based graphics with SVGs to trim those bytes.
SVG’s scalability is a huge advantage, and with retina screens becoming the norm they appear to be the answer to web designer’s problems.
SVG: the building blocks
Readers be aware, SVGs are not simple creatures. You will need to do a lot of work to understand how they behave. They’re more complicated than other standard image formats, but the control you will have will immediately win you over.
To create an SVG you need the <svg> element. It acts as the canvas and container for your vector graphics. SVGs are very similar to the canvas element whereby x and y specify the position on a grid, and the width and height work exactly as you expect. The top left corner of the grid is (0, 0), the y axis is vertical, x axis is horizontal, as is the norm. As y increases the point moves down, as x increases it moves to the right. Simple.
A quick word about scaling
Scaling SVGs is a complicated subject area in which I am not going to go into too much detail. There is a comprehensive article by Amelia Bellany-Royds called How to Scale SVG which covers all bases in great detail.
The default size for an SVG, when the width and height are set to auto, is 300px by 150px. Beware of the width and height SVG attributes. Traditionally you would expect the element to scale up or down predictably if you were to set a pixel width or height. Well it does in all browsers apart from, yes you guessed it, Internet Explorer. It will keep the default aspect ratio of 300x150 but the image itself will stay the same size, it won’t scale up or down.
Here is an example of how an SVG will display if you give it the properties width: 100%; height: auto;
The diagram on the left is how you would expect an image to behave. The diagram on the right illustrates how IE will display your SVG. The <svg> will fill the space with a width of 100% but the actual drawing, the polygon, will retain it’s original size and instead centre within <svg>. What you need to fix this is the viewBox attribute.
The viewBox is a very important SVG attribute. It specifies the aspect ratio of your graphic as well as where it should be rendered within the grid. viewBox has four values: x, y, width and height. x and y define where the graphic should be rendered within the viewBox. For example if x=’10’ and y=’50’ the graphic will be rendered slightly to the right and much further below the top left which is 0,0. The width and height define the size of the SVG viewport and subsequently it’s aspect ratio. Adding viewBox to the SVG element makes you graphic scale perfectly, and by default the aspect ratio will be preserved. In order to stop this, add preserveAspectRatio=‘none’ to <svg>.
The basic shape elements
Here is a quick summary of the basic shape elements.
- circle: defines a circle graphic. The cx and cy coordinates are positioned at the centre of the circle. The r value is the circle’s radius
- ellipse: defines an ellipse (oval) graphic. It has cx and cy coordinates which work the same as a circle. Unlike the circle it also has rx and ry values. A higher rx value will produce a wide ellipse, a higher ry value will produce and tall ellipse.
- line: renders a line dictated by a start and end point. The start point is defined using the x1 and y1 coordinates, the end point is defined using the x2 and y2 coordinates.
- path: defines a complex closed shape which can include straight lines, curves and arcs.
- polygon: defines a closed shape which comprises straight lines connected from beginning to end, i.e. a shape with more than three straight edges.
- polyline: like a polygon, comprises straight lines connected to one another. However it differs from a polygon in that it is an open shape, the end points do not connect.
- rect: defines a rectangle. It has x and y coordinates as well as width and height values. The rx and ry length values control the corners of the rectangle. As they suggest the rx controls the horizontal sides of the corners, and the ry controls the vertical sides of the corners. For perfectly rounded corners, both rx and ry need to have the same value.
Different ways to use SVGs
There are so many ways to use SVGs. Here is a rundown of the ways I know of that you can use them.
You can drop an SVG document straight into you HTML if you wish. It’s very easy, you can access the markup from Illustrator or open the document in a text editor. Make sure you look at the markup Illustrator produces, it can be bloated. It is easy enough to tidy up manually if it’s a simple SVG, otherwise there are plenty of optimiser tools to utilise on the web. What’s good about this method is there is no need for an additional HTTP request, which means a faster loading time. One issue you will comes across straight away is how bloated your markup becomes. If you have a complex inline SVG you could be scrolling for days to get to the end of it. Also, inline SVGs cannot cache. What you cut down on HTTP requests you will add on to the overall page load time.
- Browser doesn't need to make an additional HTTP request
- Quick and easy to do
- Bloats the markup
- Cannot cache
Very well supported. IE does not support CSS transforms on SVG elements however it does support the transform attribute. IE8 and below does not support inline SVGs.
As an <img>
It is possible to treat an SVG as any other image format and use it within an <img> tag. The SVG will behave just like a jpg or any other image format would, as long as you have included the viewBox attribute in the SVG document. This is an ideal way to add an SVG to a web page because it’s familiar, front end developers know how to use the <img> tag (or at least they should do!). Unfortunately you don’t have as much control over the style, you cannot for example change the fill colour of a shape.
No access to SVG markup which means not styling
Works in all browsers apart from IE8 down.
As a CSS background image
SVGs are extremely simple to use as background images. All you need to remember is to again include the viewBox attribute otherwise it starts to behave strangely in IE. Just as you do with any background image you need to set the background-size otherwise it will use it’s viewBox size. Again there will be no simple way to change fill colours with CSS alone, you will need the help of code.
Easy to use
Cannot manipulate style of SVG with only CSS
Not supported in IE8 down. Older versions of Firefox and Opera Mini/Mobile blur scaled up SVG images.
As an <object>
The <object> tag is really useful in that you can link to an SVG file externally and still have the ability to manipulate the style with CSS. Win win! The only drawback is that the <style> tag has to be within the SVG document itself. There is a way to link an external stylesheet to the SVG, see Chris Coyier’s Using SVG article.
- Can be cached
- Can use CSS to style SVG
- CSS has to be linked directly to or within the SVG document
Well supported across all browsers.
Clipping is a wonderful tool which I have used in our new website, see the Client Stories grid on the home page.
What is clipping I hear you ask? If anyone has used a graphics editing programme you will have probably clipped something at some point. Clipping is the act of hiding part of one element with another element.
An SVG clipPath is an SVG shape which is used to clip an element.
<svg width=“0” height=“0”> <defs> <clipPath id=“polygon-sq2" clipPathUnits="objectBoundingBox"> <polygon points="0 100, 20 0, 100 0, 80 100”/> </clipPath> </defs> </svg>
This shape is a polygon and not a path because it consists of only straight lines, no curves. It will render as seen below if the height and width on the SVG are not set to 0. The black fill is default. As you can see the clipPath element wraps around the shape. Make sure you add clipPathUnits=“objectBoundingBox" to clipPath otherwise the clipping won’t work in Firefox.
Now our clipPath is ready, we need something to clip.
Tada! All you need is an element to clip with the CSS property clip-path. clip-path can be used in a number of different ways, as is illustrated in the Codepen. In order for it to work in Firefox you must reference the clipPath ID. For it to work in Chrome and Safari I have taken the values from the SVG polygon and added them to the clip-path polygon and converted them to percentages. Unfortunately clip-path does not work in IE, it ignores the property and renders a standard rectangle which hopefully shouldn’t break your design. To learn more about the clip-path property take a look at Smashing Magazine’s Creating Responsive Shapes with Clip-Path and Breaking out of the Box.
The <use> tag
Lastly I want to focus on what I have found to be an extremely useful element, <use>. It is so great because you can reference an external file which the browser will cache, AND you have the ability to change the style via CSS. Here is an example of what your markup will look like:
<svg> <use xlink:href=‘defs.svg#icon’></use> </svg>
Here we are referencing an external SVG sprite sheet. How you create an SVG sprite sheet is beyond the scope of this blog post, but there are plenty of articles covering the subject. Sara Soueidan aka SVG guru has written a great blog post, An Overview of SVG Sprite Creation Techniques which you need to read. Just like any other sprite sheet all your SVGs will be listed in the document, you will need to reference each one by it’s ID.
Unlike referencing your SVG with <img>, your SVG markup is injected into what is known as the ‘Shadow DOM’. The markup is not directly accessible via your browser’s developer tools but you can change your settings in Chrome so you can view them. Again, this is outside the scope of this article, and I refer you to another blog post by the SVG guru: Styling SVG <use> Content with CSS. Soueidan explains what the Shadow DOM is and how to display the markup through Chrome. She also goes into detail about how you can style the <use> SVGs with CSS. Unfortunately it is not as simple as you might think, but Soueidan’s article goes into much detail and you will be styling your SVG’s in the Shadow DOM in no time!
One issue I came up against when implementing <use> SVGs throughout our new look website was IE’s inability to render icons from an external sprite. It had no problem rendering internal SVGs. Luckily the wonderful Chris Coyier has written a short script to ajax for the sprite, that is inject the sprite directly into your HTML. You can get the code here. Despite this wonderful piece of script I was still having timing issues with IE which meant the sprite was being injected after the page loaded. From what I can see the browser couldn’t find the SVGs being referenced in <use> because they weren’t there yet. This is what I think was happening:
- HTML loads
- CSS and scripts load
- Assets load
- SVG sprite gets injected directly beneath the opening <body> tag
- Assets have already loaded therefore SVGs have missed their chance to be injected where they have been referenced in <use>
I have not yet fixed this issue but we are going to write a script whereby if the browser is IE then the sprite will be added inline, all other browsers will use the ajax method.
- Easy to use, one line of markup
- Tidy way to reference
- Can be cached by browser
- Can be styled even if it is from an external file
- Cannot be styled in the traditional way (but still possible, see Sara Soueidan’s article referenced above)
- IE won’t load load from an external URI
There is basic support across all browsers when using an internal SVG sprite. External URIs don’t work in IE, however this can be fixed with a great script called SVG for Everybody by Jon Neal.
These are the ways I have found to implement SVGs into my work, if there are any others I have missed please get in touch! I have had many ups and downs learning (very much still learning) how to use SVGs properly but rest assure it is entirely worth it once you get your head around all the browser quirks. There are also so many great articles out there, including the ones I have mentioned, get reading and experimenting and you’ll be an SVG expert in no time!