Optimize SVG files for websites

Slimming Down

© Lead Image © Sandra Cunningham, Fotolia.com

© Lead Image © Sandra Cunningham, Fotolia.com

Author(s):

Inkscape creates W3C-compliant SVG files, but they are usually larger than they need to be for the web. We'll show you how to optimize SVG files for faster load times.

Graphic images can give a website clarity and visual interest, but the web designer must contend with the tax that heavy graphic images place on bandwidth and load time. Photo images are typically scaled down to a lower resolution (and smaller file size) to run on the web, and for other types of image files, smaller is also almost always better.

One way to reduce the size of web images is to rely on vector graphics whenever possible. The Scalable Vector Graphics (SVG) format was originally developed for use on the Internet. Although SVG typically leads to significant economies of scale when compared to pixel graphics, it has taken decades for web developers to become reasonably comfortable with it.

The most popular tool for vector graphics on Linux is Inkscape. You can certainly save some kilobytes by generating graphics files with Inkscape rather than an alternative raster graphics tool like Gimp. But using Inkscape doesn't mean your files will automatically be optimized for the web. This article highlights some steps you can take to reduce the size of vector graphics image files.

Turning Big into Small

There are two ways to display a simple circle using HTML graphics: either as a path (Listing 1) or as an SVG element (Listing 2).

Listing 1

Circle as Path

<path d="M 162.66582,125.05696 A 70.917999,70.917778 0 0 1 91.747818,195.97474 70.917999,70.917778 0
0 1 20.829819,125.05696 70.917999,70.917778 0 0 0 1 91.747818,54.139183 70.917999,70.917778
0 0 1 162.66582,125.05696 Z" style="fill:#000000;stroke:none;stroke-width:7.99999;stroke-linecap:round;
stroke-linejoin:round;stop-color:#000000" id="path10" />

Listing 2

Circle per SVG

<ellipse ry="70.917778" rx="70.917999" cy="125.05696" cx="91.747818" id="path10" style="fill:#000000;
stroke:none;stroke-width:7.99999;stroke-linecap:round;stroke-linejoin:round;stop-color:#000000" />

Two nodes are all you need for the path, but most programs use at least four, and that includes Inkscape. These extra nodes are due to the fact that slight deviations from the original path occur with only two nodes, but this extra level of precision is often unnecessary in the web context.

As you can see, the source code from Listing 1 needs far more characters and accordingly more space. As long as you can work with elements defined in SVG (Listing 2), you should do so.

Clone or Duplicate?

Graphic artists often use a duplicate of an object instead of a clone. The duplicate repeats the complete description of the object; only the coordinates and the ID change (Listing 3). A clone, on the other hand, uses the use tag with the ID of the original (Listing 4).

Listing 3

Duplicate

<ellipse
    ry="8.595953"
    rx="8.5959797"
    cy="62.735138"
    cx="29.425798"
    id="path10"
    style="fill:#000000;stroke:none;stroke-width:0.96968;stroke-linecap:round;stroke-linejoin:round;stop-color:#000000" />
<ellipse
    style="fill:#000000;stroke:none;stroke-width:0.96968;stroke-linecap:round;stroke-linejoin:round;stop-color:#000000"
    id="ellipse102"
    cx="49.26012"
    cy="62.735138"
    rx="8.5959797"
    ry="8.595953" />

Listing 4

Clone

<ellipse
    ry="8.595953"
    rx="8.5959797"
    cy="62.735138"
    cx="29.425798"
    id="path10"
    style="fill:#000000;stroke:none;stroke-width:0.96968;stroke-linecap:round;stroke-linejoin:round;stop-color:#000000" />
  <use
    height="100%"
    width="100%"
    transform="translate(21.089236)"
    id="use104"
    xlink:href="#path10"
    y="0"
    x="0" />

The code example from Listing 3 needs 488 characters, whereas the cloned variant from Listing 4 needs only 406 characters – with the same result. The difference might seem relatively small, but this is only a single simple object. In the case of more complex graphics, several kilobytes can quickly accumulate.

Some people might think that a few kilobytes do not matter today, but with many users accessing the Internet via smartphones, traffic is still relatively expensive. Some organizations also pay for data traffic on the server end, and a few kilobytes for a single image can add up to several gigabytes by the end of the month. But regardless of the traffic issues, optimization is a healthy habit for any website. Your visitors benefit from a compact website with faster load times and will be more likely to come back.

You should always remove unneeded nodes from paths, but this can only be done manually. An ideal path looks like the one shown in Listing 5.

Listing 5

Optimized Path

<path d="M504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zM212 140v116h-70.9c-10.7
0-16.1 13-8.5 20.5l114.9 114.3c4.7 4.7 12.2 4.7 16.9 0l114.9-114.3c7.6-7.6 2.2-20.5-8.5-20.5H300V140c0-6.
6-5.4-12-12h-64c-6.6 0-12 5.4-12 12z"/>

Inkscape

The majority of Linux users use Inkscape to create SVG graphics. Many users don't realize that Inkscape inflates graphics with a lot of unnecessary stuff. This starts with unused definitions and continues with the Inkscape and Sodipodi document types and ends with a heap of metadata. The web browser does not need all this information to render the graphics.

If you fill an object with a gradient, a definition will appear in the <defs> section at the beginning of the document. If you change the fill, the old definition will remain in the file. You can remove these unused definitions in Inkscape with File | Clean Document.

Save Correctly

If you use Save as… instead of File | Save as…, you can select a different file format. The output options include different SVG variants, such as Inkscape SVG, plain SVG (and its zipped variants), and optimized SVG.

If you save in Inkscape SVG, everything remains the same. Saving as plain SVG, on the other hand, removes all Inkscape/Sodipodi proprietary elements. If you use optimized SVG, a dialog box with four tabs appears. The last tab reports that Inkscape uses the SVG optimizer Scour [1].

In the first tab, Options, you can specify the significant digits for the coordinates (Figure 1). In the code example for the circle, you can see that the coordinates have six digits after the decimal point; however, you will not usually need this kind of accuracy to display a graphic on the web. If you enter a 6 in the Options tab, and the number has three digits before the decimal point, it will have three digits after; if you have tow digits before the decimal point, you will have four after.

Figure 1: If you save your file as an optimized SVG in Inkscape, this dialog will open.

If you enable the Shorten color values option, the short version is used for all color values (i.e., fill:#f00 instead of fill:#ff0000). Convert CSS attributes to XML attributes writes color values to the SVG document instead of the CSS attribute. You should not do this, for example, if you are designing icons that need to get their color values from CSS.

The Collapse Groups button removes unneeded groupings. Many graphic designers group together all or individual elements of the graphic, which makes the workflow easier. In code, a group is represented by the g tag, for example <g id="g1211"></g>. This example contains 18 bytes that are not important for correct rendering. Inkscape itself always creates a group for the layers in the document, but this kind of group only makes sense while you are working on the drawing, not when it is displayed.

The Create groups for similar attributes option creates groups for objects with the same fill color and outline. The software then writes the values for the attributes to the g tag, for example <g fill="#f00">. All the objects in this group are therefore black, which removes the need for the corresponding attribute for each object (i.e., a minimum of 10 characters with two objects).

The Keep unreferenced definitions option keeps the unreferenced definitions. Work around renderer bugs tries to work around known rendering bugs in some engines. However, all web browsers render SVG quite well, so you don't really need this switch.

The second tab SVG Output (Figure 2) also contains some options. The option Remove the XML declaration is not needed to render the graphic. However, it should be kept if the graphic contains text with special characters.

Figure 2: The Optimize dialog with the tab for customized SVG output.

It makes sense to enable the next option Remove metadata – there is sometimes quite a large volume of metadata, such as the author and license entries. Remove comments deletes comments contained in the document; Embed raster images writes existing raster images as Base64 code into the SVG document.

The Enable viewboxing checkbox is interesting; you can often see faulty files with it. The viewport is the visible image area and can be compared with a window where all or only part of the view is shown.

The size of the viewport is defined by the attributes width and height. The dimension for the viewbox is often the size of the document, so you first need to adjust the page size accordingly. To adjust the page size, open the File | Document Properties dialog and enable Resize page to content…. Then click on Resize page to drawing or selection.

The IDs tab of the Optimized SVG output dialog(Figure 3) lets you remove or shorten unused IDs. In SVG, every object is given an ID, but this ID is often longer than necessary. You usually only save one or two bytes, but the sheer mass of the data can add up.

Figure 3: The tab with the ID functions in the Optimize dialog.

If you now save the file as SVG, it will be far smaller. By how much depends on the complexity of the graphic: The more complex, the greater the savings – usually around 50 to 65 percent.

Alternatives

Optimizing vector graphics in the Inkscape GUI can take some time. It is also possible to call Inkscape at the command line, although the command-line options are limited to cleaning up definitions.

Inkscape uses the file extension on the command line to determine what to save the file as. SVG stands for Inkscape SVG only.

The Scour command-line tool is a better choice for optimizing an Inkscape file at the command line; Listing 6 shows its syntax.

Listing 6

Using Scour

$ scour input_filename.svg output_filename.svg --create-groups --no-renderer-workaround --remove-descriptive-elements
--enable-comment-stripping --enable-viewboxing --no-line-breaks --strip-xml-space --enable-id-stripping --shorten-ids

There are other tools for editing and optimizing SVG files, for example SVGO [2]. However, very few distributions have SVGO in their repositories. To install it anyway, use the Node.js package manager:

$ sudo npm install -g svgo

SVGO follows a philosophy that is different from Scour, so the call is less complex:

$ svgo -i filename.svg

The command overwrites the filename.svg file with the optimized version. If you want to save it in a separate file, use the -o new_filename.svg switch.

SVGO performs some operations that Scour does not offer. For instance, SVGO compares path values and converts duplicates into clones. You can enable this option with the --reusePaths option.

SVGO also comes with a function for recursive operations and can therefore be applied to directories. In Scour, you would have to write a small script for recursion. In any case, SVGO is the more modern tool. A plugin exists for using SVGO directly from within Inkscape [3], but currently it does not work.

Another tool for cleaning SVG files is svgcleaner [4]. Svgcleaner has a graphical user interface called SVG Cleaner [5]. This tool is also rarely found in the repositories of the popular distributions. Since the GUI is written in Qt, you have to compile it yourself.

The developers implemented svgcleaner in Rust, so you can install it using the Rust package manager Cargo:

cargo install svgcleaner

Svgcleaner takes an even more radical approach than SVGO and creates even smaller files. If you work with CSSs in SVG, make sure you avoid the svgcleaner program, because it also removes CSS attributes.

Since Rust writes the binary file to a separate subdirectory of its home folder, you first need to change the directory, and when you get there, call svgcleaner:

$ cd /home/user_name/.cargo/bin/
$ ./svgcleaner input_filename.svg output_filename.svg

Conclusions

Even if you're a vector graphics beginner, the tools and techniques described in this article will help you get started with optimizing your SVG web files. Smaller files will mean faster load times for your website visitors – and could also lead to less traffic and lower costs for you and your customers. However, it is important to note that all the tools described in this article are not designed to work with the next generation W3 vector-graphics standard SVG 2.0, which is currently at the draft stage.

The Author

Sirko Kemter has been involved with Inkscape since the program began and has written a book about working with Inkscape. In his spare time, he creates graphics for Openclipart and various open source projects. Because he lives in Southeast Asia, and people there tend to use mobile devices, he has been working for some time on optimizing websites to reduce their size and load times.