You wouldn't think that the SVG format has been around for almost 20 years.
Over the last few years, the popularity of the format has grown so phenomenally that you'd be forgiven for thinking it was a recent innovation.
These days, it is common practice to provide your logo, graphics, charts, and the like as an SVG, instead of its pixellated bitmap counterparts.
So, where did this file format come from? The SVG (Scaleable Vector Graphic) format was brought to the table in 1999 by the W3C (World Wide Web Consortium). It's an XML based vector image format designed specifically for the web.
One of the many beauties of vector images, including SVG, is that they can be scaled to any size without a loss of quality. Bitmap images, on the other hand, such as .jpg, .png, and .gif, pixelate when scaled beyond their natural size.
Scalability makes the SVG format a natural fit for the responsive web. An SVG can easily be scaled for mobile, desktop, all the way to 5K displays, and everywhere in between and beyond.
An SVG typically has a smaller file size than any of its bitmap counterparts. An SVG also supports several interesting use cases that bitmaps cannot, including animation and interaction with JavaScript.
If you’re not yet convinced that SVGs are the future, I strongly recommend watching this Chris Coyer video or reading Chris’ book, Practical SVG.
Convincing readers to use the format is not the purpose of this article. Rather, this article is a guide for those who have already adopted SVGs, and want to squeeze a little more out of the format.
Let's explore how we can cleanup SVG markup, and why we probably should.
SVG Anatomy (SVG == Markup)
When you preview an SVG in a browser or an image viewer, it will, more or less, behave as a bitmap. You can see the image rendered. Of course, the SVG will be sharper, and won't pixelate if you zoom in, but beyond that there is little difference.
The difference is behind the scenes. SVG is XML-based. Behind every SVG there is readable, HTML-like markup. This means that you have readable line-by-line control, regardless of what tool churned out the file.
Heck, SVGs could be coded from scratch, and often are. But, most SVGs are produced in a graphics editor, such as Adobe Illustrator, Inkscape or Sketch. These applications often export their SVG markup with superfluous, and sometimes outdated, elements and attributes.
For example, here is the XML from an SVG icon created in Adobe Illustrator:
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 60 60" style="enable-background:new 0 0 60 60;" xml:space="preserve">
<g>
<path d="M45.563,29.174l-22-15c-0.307-0.208-0.703-0.231-1.031 0.058C22.205,14.289,22,14.629,22,15v30c0,0.371,0.205,0.711,0.533,0.884C22.679, 45.962,22.84,46,23,46c0.197,0,0.394-0.059,0.563-0.174l22-15 C45.836,30.64,46,30.331,46,30S45.836,29.36,45.563,29.174z M24,43.107V16.893L43.225,30L24,43.107z"/>
<path d="M30,0C13.458,0,0,13.458,0,30s13.458,30,30,30s30-13.458,30-30S46.542,0,30,0z M30,58C14.561,58,2,45.439,2,30S14.561,2,30,2s28,12.561,28,28S45.439,58,30,58z"/>
</g>
</svg>
If you’re familiar with HTML, this will look quite familiar: it's just elements and attributes.
And, just like HTML, we can optimise it.
Let’s look at another example. This SVG markup is for a map marker icon generated by Sketch:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="39px" height="39px" viewBox="0 0 39 39" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
<title>Hospital</title>
<desc>Created with Sketch.</desc>
<defs>
<rect id="path-1" x="0" y="0" width="33" height="33" rx="9"></rect>
</defs>
<g id="Maps" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Map" transform="translate(-483.000000, -779.000000)">
<g id="Hospital" transform="translate(486.000000, 782.000000)">
<rect id="Rectangle-57" fill-opacity="0.599999964" fill="#FFFFFF" opacity="0.5" x="0" y="0" width="33" height="33" rx="9"></rect>
<g id="Rectangle-57">
<use stroke="#2D2D2D" stroke-width="6" fill-opacity="0.599999964" fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-1"></use>
<use stroke="#FF0000" stroke-width="3" xlink:href="#path-1"></use>
</g>
<polygon id="Shape" fill="#FF0000" points="19.7149758 19.5157005..."></polygon>
</g>
</g>
</g>
</svg>
Sketch generated this simple icon with 21 lines of markup.
Relative to a typical HTML file, that is not many lines. But, for a simple icon, it's much more than necessary. Most icons that I work with are around 4-10 lines.
Why the bloat? There are several elements and attributes that are redundant and can be removed. Let's have a look at what they are, and why we can remove them.
What Markup can we remove?
XML Prolog
The first thing that we can remove is the first line: the XML prolog.
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no”?>
Most XML documents begin with a prolog. A prolog is one or more lines of code that provide information about the current XML document and related documents.
If the SVG is going to be embedded within an HTML document or another SVG, which it most likely will be, the prolog is redundant and can be removed.
Leaving the prolog will have no effect to the user, but removing it helps keep your code clean and reduces file size.
The <svg>
version Attribute
The <svg>
tag comes packaged with the version
attribute, indicating that it is using the latest version of SVG – SVG 1.1.
<svg version=”1.1″ … >
This attribute has no influence on the rendering of the SVG and can be removed.
XML Comments
Did you see Sketch's obtrusive XML comment?
<!– Generator: Sketch 39.1 (31720) – http://www.bohemiancoding.com/sketch →
Although in certain contexts, XML comments can be helpful, this particular comment is redundant. We don't need to know where the icon came from.
Many other graphic editors include XML comments when generating SVGs, and these comments can also be safely removed.
The <title>
and <desc>
tags
Next, we’re going to look at the title
and desc
elements.
<title>Hospital</title>
<desc>Created with Sketch.</desc>
You may not want to remove these elements. It depends upon the context in which the SVG will be used.
The title
and desc
tags are helpful for accessibility. The title
element is displayed on hover in certain browsers. Both elements may also be displayed instead of the graphic if there is a situation where the SVG paths cannot be rendered.
If the SVG provides important context to the page, for example, a graph or chart, then you should keep the title
and desc
tags, and change their text content to convey the content of the graphic.
On the other hand, if the SVG does not provide important context, for example, an icon or logo, then the title
and desc
tags can be removed.
As I am working with an icon in this example, I removed the tags.
The <g>
tags
The major clutter of the SVG markup in my example is the chain of <g>
tags that serve as a wrapper for the SVG paths.
Most of the <g>
elements have a transform
attribute, among others.
<g id="Maps" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Map" transform="translate(-483.000000, -779.000000)">
<g id="Hospital" transform="translate(486.000000, 782.000000)">
<rect ...></rect>
<g id="Rectangle-57">
<use ...></use>
<use ...></use>
</g>
<polygon ...></polygon>
</g>
</g>
</g>
All of these <g>
elements are redundant and can be removed.
Why Sketch decides to leave an endless trail of <g>
tags in its wake is one of life's great mysteries. We may never know.
The <svg>
viewBox
Attribute
The <svg>
viewBox
attribute is a complicated concept.
I will not delve into it within this article, but I strongly recommend Sara Soueidan’s article if you are unfamiliar with the attribute.
<svg viewBox=”0 0 39 39″ … >
Once the <g>
tags were removed, the positioning of the SVG elements was slightly off by 3 pixels. I adjusted the starting point of the viewBox
to compensate.
<svg viewBox=”-3 -3 39 39″ … >
This isn’t ideal, but it’s better than the endless chain of <g>
tags and their non-sensical transform
attributes.
Although I did, you may not have to make any edits to the viewBox
attribute. But, if you do, it is likely that you will have to use different values.
IDs
Most of the SVG elements were generated with an id
attribute. The <rect>
element, for example:
<rect id=”Rectangle-57″ … />
Unless you need to target these elements with JavaScript, these id
attributes can be stripped out. The only instances where the id
attributes are important are within the <defs>
block.
In my example, the <defs>
block looks like this:
<defs>
<rect id=”path-1″ x=”0″ y=”0″ width=”33″ height=”33″ rx=”9″></rect>
</defs>
The elements within the <defs>
are not initialised within this block, but rather they are declared for future use.
You can see the path-1
element defined within the <defs>
block is referenced later in the markup via a <use>
element:
<use xlink:href=”#path-1″ … ></use>
That means we need to keep the id
attribute so that the <use>
element can reference the <rect>
. But, the id
value path-1
is not descriptive. I renamed it to border
:
<defs>
<rect id=”border” x=”0″ y=”0″ width=”33″ height=”33″ rx=”9″></rect>
</defs>
<use xlink:href=”#border” … ></use>
The new id
clearly describes the element.
What's next?
Okay, lets address the elephant in the room...
Why not use an automated SVG optimiser, like SVGO or SVGOMG?
It's true. There are a number of automated tools that will optimise SVG markup for you.
But, this can come at a cost.
In some cases, automated tools can merge all of the SVGs layers, making the SVG harder to work with in future.
To quote Sarah Soueidan:
[SVGO] can break the SVG as well as any structure you create in it for animation, for example. I use SVGO sparingly. Ai export is v clean.
Here is an interesting Twitter thread on the topic by Sara Soueidan et al here, which is also the source of the above quote.
Conclusion
And that’s it.
<svg width="39px" height="39px" fill="none" viewBox="-3 -3 39 39" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<rect id="border" x="0" y="0" width="33" height="33" rx="9"></rect>
</defs>
<rect fill-opacity="0.6" fill="#FFFFFF" opacity="0.5" x="0" y="0" width="33" height="33" rx="9"></rect>
<use xlink:href="#border" stroke="#2D2D2D" stroke-width="6" fill-opacity="0.599999964" fill="#FFFFFF" fill-rule="evenodd"></use>
<use xlink:href="#border" stroke="#FF0000" stroke-width="3"></use>
<polygon fill="#FF0000" points="19.7149758 19.5157005..."></polygon>
</svg>
We’ve managed to reduce the lines of code down to 9 -- over 50% of the lines of code were removed. That’s pretty impressive.
Now, you’re probably wondering what the point of all this cleanup was.
Well, clean SVG markup has a myriad of benefits, including:
Maintainability – your SVGs are easier to edit and maintain, without ever opening an image editor.
Speed – less code means smaller file sizes, smaller file sizes means a faster loading web page.
Animation – it becomes notably easier to animate SVGs when the markup is optimised and free from redundant tags.
Accessibility – image editors seldom focus on accessibility when generating markup. Having clean markup makes it easier to create accessible graphics.
JavaScript – understandable markup makes it easier to integrate with JavaScript. For instance, sensible, unique
id
attributes.
While it is true that an SVG minifier, such as SVGOMG, can do most of the leg work for you, it can also damage the quality of the SVG.
Do you have the time? Are you going to animate the SVGs? It's contextual and the choice is yours.
Thanks for reading.
Top comments (8)
I worked on one project where someone decided SVG was too complicated and converted them all to PNG files.
Guess what happened when the application was on anything other than 100% scale? That's right... it looked like @$$.
All that fine SVG converted into sad bitmaps. And not just bitmaps... bitmaps for all the different states. Which could easily have been done with SVG w/CSS.
Sad panda.
In some cases, you can do even more optimization by hand: some exports I received from our designers had base64-encoded jpeg-blurs and -shadows in them. So I handcoded a blur and a shadow filter and used them on parts of the design, bringing down a 30kb SVG (that was supposed to replace a 50kb PNG) to 7.5kb.
As a front-end developers, SVG is the bridge between development and design; thus to unleash it's full potential, you need a designer and a developer. Tools will only bring you so far.
Nice article, i was looking for the title issue i had with icons in an Electron app. I "fixed" by manually deleting the title tag. But there must be a better way. I mean who is going to do such work if you have perhaps more than 100 ions in a project?
Thanks 😊
In that case, you can use an SVG minifier!
Maybe build an optmisier that applies just the here described rules?
There's a challenge for you 😊
Great read, had to write a wiki page similar to this for my team. Link for Chris Coyer video?
Thanks! I've added that link in there now, and a few others I was missing :)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.