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.
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.
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.
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.
<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.
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.
Next, we’re going to look at the
<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.
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
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
desc tags can be removed.
As I am working with an icon in this example, I removed the 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.
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″ … >
<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
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.
Most of the SVG elements were generated with an
id attribute. The
<rect> element, for example:
<rect id=”Rectangle-57″ … />
id attributes can be stripped out. The only instances where the
id attributes are important are within the
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 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
path-1 is not descriptive. I renamed it to
<defs> <rect id=”border” x=”0″ y=”0″ width=”33″ height=”33″ rx=”9″></rect> </defs> <use xlink:href=”#border” … ></use>
id clearly describes the element.
Okay, lets address the elephant in the room...
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.
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.
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.