How, and why, to clean SVG markup
Tags: svg, markup, xml
Published: 2017-10-24 19:50:52

---
title: How, and why, to clean SVG markup
published: true
description: How to cleanup SVGs for simpler markup and faster loading. Plus, a comparison with automated SVG minification tools.
tags: svg, markup, xml
---

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.

<img src="https://thepracticaldev.s3.amazonaws.com/i/36z13rvrk142v181pz33.png" alt="">

[Image source](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics)

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 <a href="https://www.youtube.com/watch?v=tsGa-gcckwY">this</a> Chris Coyer video or reading <a href="https://abookapart.com/products/practical-svg">Chris’ book, Practical SVG</a>.

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 <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/version">no influence</a> 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 <a href="https://www.sarasoueidan.com/blog/svg-coordinate-systems/" aria-label="SVG Coordinate Systems article">article</a> 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 <a href="https://github.com/svg/svgo">SVGO</a> or <a href="https://jakearchibald.github.io/svgomg/">SVGOMG</a>?

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:

<blockquote>[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.</blockquote>

Here is an interesting Twitter thread on the topic by Sara Soueidan et al <a href="https://twitter.com/SaraSoueidan/status/922792186839748614" aria-label="Sara Soueidan's Twitter Thread discussing SVG optimisation">here</a>, 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.