Thursday, April 18, 2024

Getting Started with SVG

Scalable Vector Graphics (SVG) is an image format whose specification is defined by the W3C. SVG describes two-dimensional vector graphics using XML markup. You can think of it as the HTML equivalent for images.

Instead of defining images with columns and lines of pixels, SVG uses geometric primitives such as points, lines, curves and polygons to represent the image. This is what we call vector graphics. The difference is in the way these images work when we increase their size. Since vector images use mathematical expressions to resize the graph, we have no loss in defining the image.

Focusing on SVG, we have other advantages:

  • As they are text files, we can serve the images with gzip, which has an excellent compression factor.
  • Works great on high-density screens such as those on the iPhone and MacBook Pro Retina.
  • It may be manipulated through JavaScript.

But not everything is beautiful. Depending on the browsers you need to support, you might have to fallback to raster images, such as PNG. Internet Explorer only started supporting SVGs from version 9 and in Android 2.3, for example, it is not supported. SVG performance can also be a problem if you need to animate many images simultaneously. This is not the case with raster images.

Creating SVG Files

Although SVG files are only XML, you are much more likely to use a vector image editor to create your graphics. The most common alternatives are Adobe Illustrator and Inkscape, but on the Mac there is another very good alternative called Sketch.

SVG works best when the image is not that complex. This is because its size can increase a lot depending on what you are going to do; solid colors are much smaller than gradients, for example. This does not mean that you cannot have complex graphics but keep the file size issue in mind if you are going to use this SVG on a website.

If you use Adobe Illustrator, there are some things you can do to reduce this complexity when exporting SVG. Other applications may have similar functionality, but I don’t know how each of them works.

The first thing to do is to expand the graphics, modifying the attributes that define its appearance and other properties of elements that are within it. This will also help with things like opacity and gradients, although it doesn’t always work well.

Select the graph, go to the Object > Expand menu. If the chart has defined appearance attributes, you will need to select Object > Expand Appearance first.

Expanding Graphics in Illustrator

Another thing you can do is put the different parts of the chart together. Display the Pathfinder options panel at Window > Pathfinder and choose the “Merge” option. Sometimes the graph changes (things like opacity stop working) and we undo that option.

Always set the artboard close to the graphic. This can be done easily through the Object > Artboards > Fit to Artwork Bounds option.

Finally, when exporting, there are also some things to do.

Choose the SVG 1.1 profile, which has the greatest compatibility between browsers. The SVG Tiny 1.1 profiles and variations are aimed at mobile devices but do not yet have good support.

If you don’t need to manipulate text dynamically, convert all fonts to objects. This will make the text retain the characteristics you have defined, without increasing the final file size, since for all intents and purposes the texts will only be objects.

Files exported by editors can be optimized. The files generated by Illustrator, for example, always have elements that can be removed, in addition to redundant attributes. You can use a tool like SVGO to automate this optimization process.

To install it, you will need Node.js.

npm install -g svgo

Now, run the following command to optimize the SVG:

svgo logo.svg logo.min.svg

Ready! Now just add SVG to your HTML document.

Adding SVG to HTML

There are a few different ways to add SVG to HTML. The simplest way is to use the <img> tag to do this.

<img src="logo.svg" alt="My logo">

The <object> tag also works very well.

<object type="image/svg+xml" data="logo.svg"></object>

Finally, you can add the <svg> tag directly to your document. Just open the file and copy the <svg> element.

This method has advantages and disadvantages. The main advantage is that you can manipulate the background color and borders of SVG elements with CSS, for example.

circle { 
   fill: blue; 
}

The disadvantage, however, is that you can no longer rely on the browser cache since the element will be added directly to the document.

You can also use SVG as background images. To do this, just reference the file as you already do with PNGs, for example.

.logo {
  background: url(logo.svg) no-repeat;
  height: 356px;
  width: 408px;
}

A very common technique is to encode the SVG in Base64 and add it directly to the CSS file. You can do this using the base64 command, available on * nix systems. Sorry, Windows users, I have no idea how that works in Windows.

$ base64 sample.svg  | pbcopy

With this content in hand, we can now add this directly to the CSS, using data URIs.

.logo {
  width: 20px;
  height: 20px;
  background: url(data:image/svg+xml;base64,PHN2ZyBpZD0iQ2FwYV8xIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA1MTIgNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGc+PHBhdGggZD0ibTEyMCAyNTZjMC0yNS4zNjcgNi45ODktNDkuMTMgMTkuMTMxLTY5LjQ3N3YtODYuMzA4aC04Ni4zMDhjLTM0LjI1NSA0NC40ODgtNTIuODIzIDk4LjcwNy01Mi44MjMgMTU1Ljc4NXMxOC41NjggMTExLjI5NyA1Mi44MjMgMTU1Ljc4NWg4Ni4zMDh2LTg2LjMwOGMtMTIuMTQyLTIwLjM0Ny0xOS4xMzEtNDQuMTEtMTkuMTMxLTY5LjQ3N3oiIGZpbGw9IiNmYmJkMDAiLz48cGF0aCBkPSJtMjU2IDM5Mi02MCA2MCA2MCA2MGM1Ny4wNzkgMCAxMTEuMjk3LTE4LjU2OCAxNTUuNzg1LTUyLjgyM3YtODYuMjE2aC04Ni4yMTZjLTIwLjUyNSAxMi4xODYtNDQuMzg4IDE5LjAzOS02OS41NjkgMTkuMDM5eiIgZmlsbD0iIzBmOWQ1OCIvPjxwYXRoIGQ9Im0xMzkuMTMxIDMyNS40NzctODYuMzA4IDg2LjMwOGM2Ljc4MiA4LjgwOCAxNC4xNjcgMTcuMjQzIDIyLjE1OCAyNS4yMzUgNDguMzUyIDQ4LjM1MSAxMTIuNjM5IDc0Ljk4IDE4MS4wMTkgNzQuOTh2LTEyMGMtNDkuNjI0IDAtOTMuMTE3LTI2LjcyLTExNi44NjktNjYuNTIzeiIgZmlsbD0iIzMxYWE1MiIvPjxwYXRoIGQ9Im01MTIgMjU2YzAtMTUuNTc1LTEuNDEtMzEuMTc5LTQuMTkyLTQ2LjM3N2wtMi4yNTEtMTIuMjk5aC0yNDkuNTU3djEyMGgxMjEuNDUyYy0xMS43OTQgMjMuNDYxLTI5LjkyOCA0Mi42MDItNTEuODg0IDU1LjYzOGw4Ni4yMTYgODYuMjE2YzguODA4LTYuNzgyIDE3LjI0My0xNC4xNjcgMjUuMjM1LTIyLjE1OCA0OC4zNTItNDguMzUzIDc0Ljk4MS0xMTIuNjQgNzQuOTgxLTE4MS4wMnoiIGZpbGw9IiMzYzc5ZTYiLz48cGF0aCBkPSJtMzUyLjE2NyAxNTkuODMzIDEwLjYwNiAxMC42MDYgODQuODUzLTg0Ljg1Mi0xMC42MDYtMTAuNjA2Yy00OC4zNTItNDguMzUyLTExMi42MzktNzQuOTgxLTE4MS4wMi03NC45ODFsLTYwIDYwIDYwIDYwYzM2LjMyNiAwIDcwLjQ3OSAxNC4xNDYgOTYuMTY3IDM5LjgzM3oiIGZpbGw9IiNjZjJkNDgiLz48cGF0aCBkPSJtMjU2IDEyMHYtMTIwYy02OC4zOCAwLTEzMi42NjcgMjYuNjI5LTE4MS4wMiA3NC45OC03Ljk5MSA3Ljk5MS0xNS4zNzYgMTYuNDI2LTIyLjE1OCAyNS4yMzVsODYuMzA4IDg2LjMwOGMyMy43NTMtMzkuODAzIDY3LjI0Ni02Ni41MjMgMTE2Ljg3LTY2LjUyM3oiIGZpbGw9IiNlYjQxMzIiLz48L2c+PC9zdmc+)
}

With this technique we can count on the browser’s cache and load the graphics in a single request — but keep an eye on the file size as it can easily get too big.

Compression

Because it is a text-based file, SVG has an excellent compression factor. A 10KB file, for example, drops to 3.2KB when served with gzip.

If you use the Data URI technique, a file containing 13KB drops to 4.9KB when served with gzip.

Fallback

The drawback is that if you need to support IE8, you will need to fallback to PNGs, for example. A simple way to do this is to use the images’ onerror event, which is launched when an SVG tries to load. Just add the function below to <head> and define the event in the images.

<script>
  function toPNG(image) {
    image.onerror = null;
    image.src = image.src.replace(/.svg$/, ".png");
  }
</script>

<img src="logo.svg" alt="Logo" onerror="toPNG(this);">

Another technique that can be used is with the <object> tag. It is possible to define content that will be rendered if the browser does not support SVG. One problem with this technique is that the PNG image is always loaded, even when the browser supports SVG.

<object data="logo.svg" type="image/svg+xml">
  <img src="logo.png" alt="Logo">
</object>

In the case of background images, I use Modernizr. When a browser that does not support SVG is detected, a no-svg class is added to the <html> tag, allowing you to display the PNG conditionally.

.logo { background-image: url(logo.svg); }
.no-svg .logo { background-image: url(logo.png); }

In Conclusion

SVGs are almost always small, do not need a larger version for Hi-DPI screens and they have an excellent compression factor.

The sprite issue may not be that simple, but it is possible. Alternatively, you can use Data URIs, which will also be served with gzip.

Take a test. The chances of you wanting to use it for everything are great!

About the Author

Diogo Souza works as a Java Developer at PagSeguro and has worked for companies such as Indra Company, Atlantic Institute and Ebix LA. He is also an Android trainer, speaker at events on Java and mobile world.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured