Making SVG Easier to Use (Why We Build Nano)
There are a multitude of ways to embed SVG, each of them fraught with gotchas and compromises. In our quest to make SVG easier to use, we looked at different approaches and this is the story on why we build Nano.
When we produce a PNG image, we use an
<img> tag or a css background, and that's about it. It is dead simple and guaranteed to work.
Unfortunately, the same cannot be said for SVG, despite it's many advantages. Although you're spoilt for choice when using SVG in HTML, it really boils down to
<img>, all with serious gotchas and trade offs , see The best way to embed SVG on HTML (2019).
- CSS background image is not discussed because it has the same requirements as an
The problems with inlining SVG
If you're inlining SVG, you lose the ability to use browser cache, GZip compression between servers and browsers, and search engine image indexing (inline SVG is not considered an image). Even though your image may not have changed one bit, they are always reloaded and this causes slower loading times for your website, a trade off that most, are not willing to tolerate.
In addition, inlining SVG also causes complex dependency problems where you cannot easily insert images into HTML and have to resort to scripts (PHP or otherwise). When you have more than a few images, this becomes a huge problem when it comes to maintaining your site, because essentially you can't use the
<img> tag anymore.
No doubt, there are areas where inlining SVG shines, that is if you want your images to display really quickly, without waiting for other resources to load, but apart from that, clearly, you just can't inline everything.
The problems with
SVG is well known for its excellent quality when displayed on devices of all resolutions and it's ability to refer to external resources like CSS and fonts while keeping the file size very small. The idea is to have many SVG that all share a single CSS or a single font file, to reduce the amount of resources you have to download.
The myth of resource sharing
Unknown to many, sharing of external resources for SVG only applies to inline SVG. Because usage of
<object> tags allow access to these resources, the perception is that the browser will download a single copy of your CSS, even though you have many
<object> tags referring to the same CSS file.
This however, is not true at all:
Compounding the problem is the fact that
<object> tags are not recognized as an image, and therefore image search indexing is not possible.
Further compounding the problem are dependency issues, for example, if you have 100 images, and 25 of them uses Roboto, another 25 uses Lato, 25 uses Open Sans, while the rest uses a combination of the 3 fonts. Your CSS would need to refer to all 3 fonts because it is quite impossible to keep track of which file is using which fonts, meaning you may be loading fonts you may not require on certain pages.
That leaves us with the
<img> tag, which has a lot going for it. Because it's the same tag used for other image formats, you get familiarity, browser caching, GZip compression and image search. Each image is self contained, with no dependency issues.
The only problem is, you will lose your fonts. To be more precise, if you have any text in your SVG, unless you embed fonts, your text will be displayed with system fonts, mostly Times New Roman. You've spent hours selecting a beautiful font but the moment you use the
<img> tag to embed SVG, all that is lost. How can this be acceptable?
Investigating font rasterization
Our first reaction, is to see if we can perform font rasterization. It is a commonly used technique to convert fonts into paths, so it'll render well on all devices and maintain zero dependencies. On the surface, this works very well, and on the editor, everything looks perfect.
Although the rasterized SVG came in at a whopping 137KB compared to 15.7KB before rasterization, we were optimistic, because after optimizing our SVG using GZip compression, the rasterized file is reduced to 11KB, slightly smaller than the equivalent PNG at 11.9KB.
Alas, once we embed the rasterized SVG into HTML, we found our optimism to be premature. Although it might look great on high resolution displays, quality on low resolution displays are unacceptable.
The bottom of the image is the original, with fonts displaying clearly while on top, fonts are pixelated.
What's happening is that most operating systems will optimize fonts to ensure they are shown clearly and sharp on all screens. On Windows, this is called ClearType, and since we rasterized our fonts, no optimizations will be applied, resulting in blurred text, particularly visible on low resolution screens.
Obviously, a reduction in quality is unacceptable, so back to the drawing board.
Font embedding to the rescue
Initially, we were extremely skeptical about font embedding, mainly because of the complicated workflow.
To embed fonts in SVG, you first have to know what font families are used. Then you need to find these font files and download them. Once downloaded, you have to convert regular, bold, italics and bold italics to base 64 encoding. If you're doing it manually, it is quite impossible, over a large number of files, to know which file uses bold and which ones does not. Then you have to copy all 4 base 64 encoded strings into your SVG.
Surely, there is a better way. It's here, we first develop Nano, and ensure Nano scans SVG automatically and insert only the fonts being used. For example, if bold is not used or if no text exist, then no fonts will be embedded.
Still, as you can imagine, the resulting file is huge and is not competitive with equivalent PNG. So we plugged away and built our own SVG optimizer that will reduce SVG file sizes to a trickle (see How Nano compresses SVG). In addition, we also optimized how we embed fonts into the SVG, resulting in very small file sizes.
Comparing file sizes and bandwidth savings
Nano font embedding
From the above we can see that Nano produces an SVG that is extremely lightweight even with embedded fonts, coming in at 11.7KB (GZip) compared with equivalent PNG @1x at 11.9KB. While this may not seem significant, total bandwidth saved on your site will surely be significant.
Assuming that 50% of your traffic is low resolution, 40% at 2X resolution while the rest of the 10% at 3X resolution. If your website has 10,000 hits on a single image:
5000 * 11.9KB + 4000 * 26.5KB + 1000 * 42.6KB =
If you use Nano compressed SVG with GZip: 10000 * 11.7KB =
This will result in: 208.1KB - 117.0KB =
91.1KB savings, or
43.7% bandwidth savings, a significant amount, by any measure.
In addition to the bandwidth savings, you get a far simpler workflow without resorting to multiple PNG images and using
srcset, with much better quality including operating system font enhancement to ensure your images stay crisp and sharp on devices of all resolutions, and best of all, a better user experience for your users, since your site will load faster, especially so, on devices with high resolution.
Thoroughly testing Nano
Not satisfied with all the savings, we began to look for SVG images to thoroughly test Nano. A total 2571 (and growing) SVG files of various sizes and design were used, totaling
16.3MB and after Nano optimization, resulting in
6.2MB, an astonishing
61.8% savings in file sizes.
Showing a visual difference
Because of the sheer number of files we are testing, and increasing all the time, we have to build an automated test, including automatically highlighting pixel differences before and after optimization. One of the complaint about other SVG optimizers is the fact that minifying SVG may break your image, causing it to render differently compared to the original.
To this end, we carry over the pixel differentiation in our testing into Nano itself, that is Nano will warn you if it detects the SVG it optimizes, has a pixel difference of more than 1% when compared to the original, therefore ensuring Nano's optimization will never break an SVG.
What does Nano has to offer?
Incomparably low file size
With or without font embedding, Nano offers one of the lowest file size, thus saving bandwidth and resulting in faster loading times for your website.
Greatly simplified workflow
If you're using PNG images for multiple resolutions, you'll need a script to produce multiple PNG with different resolution, in addition to having scripts to insert
srcset into your
<img> tag. Despite these, users with high resolution displays (mostly mobile users) will still be penalized and forced to download a high res image to ensure quality.
Nano offers a simplified process without the need to produce multiple images, with a file size that is comparable to the lowest resolution and yet offers the highest quality on all resolutions, plus rewarding users with high res displays with speedy loading.
Far better quality by preserving fonts
Because fonts are embedded and preserved, plus SVG being a vector graphics format, rendering quality on all resolution is incomparable to other raster formats.
We hope our work will make SVG easier to use everywhere, and is working on even smaller file sizes, porting our codes to work on Node.js so you can automate your production builds with Nano, among others.
We would love to hear your feedback, so please do not hesitate to comment below.
Originally published at CSS-TRICKS on June 21, 2018