SVG is a lie.
Tags: frontend, webdev, performance, tutorial
Published: 2023-04-08 15:55:08

SVG is a lie.

> "What?" You might ask. "It obviously exists, what are you talking about? Are you stupid?"

Yes, SVG exists. What is a lie about it is the mystique it has, the widely spread misconception that SVGs are a small and efficient way to store images. That might have been true at some point in the past, but not anymore, at least most of the time.

> "But SVGs are just vector graphics, they should be really small and efficient!"

I would agree, there should be no world where raster images would be smaller than vector graphics but here we are.

It turns out that SVGs are actually XML and plain text. Fortunately we moved as an industry away from XML, but there are still vestiges, such as HTML or SVG. Plain text is not really the most efficient way to describe images, unless you're doing it by hand, and I'm against editing SVG manually. We got tools for that! 
Unless you're doing something really simple like an x of a hamburger menu you should probably stay away from it.

You can think about SVGs like having O(1) complexity, but with a high baseline cost. Yes, when you scale them up they will be extremely efficient but when they're small, which is almost always, they will lead to increased bundle sizes and if you have a lot of them it might get a bit slow.

![Your network on svg](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e11m9eh126pla8uwjwvk.png) 
> Your network on svg



## My findings

The most common use case for SVGs is icons. Most icons get designed and created in vector graphic editors like [inkscape](https://inkscape.org/) or [Adobe Illustrator](https://www.adobe.com/products/illustrator.html).

Icons tend to be small, ~16-50px

Let's run an experiment. For my personal website I downloaded a bunch of icons for the technologies and programming languages I know. Some of them happened to be SVG. Let's see their sizes:

```
$ find . -name "*.svg"  -exec ls -lh {} \; | awk '{print $9, $5}' | sort
./css.svg 473
./c.svg 1,4K
./c++.svg 1,6K
./docker.svg 1,4K
./git.svg 703
./go.svg 1,7K
./nodejs.svg 1,7K
./postgres.svg 4,3K
./python.svg 1,1K
./rabbitmq.svg 745
./react.svg 11K
```

Here we can see that the average icon is ~1KB, except for a few outliers. It's ironic that the biggest one is react, a framework famous for being bloated and slow. :P

Let's try now in webp format! The webp folks have done a great job, [claiming 25% size decreases over png](https://developers.google.com/speed/webp/docs/webp_lossless_alpha_study) and [25/35% over jpeg](https://developers.google.com/speed/webp/docs/webp_study) The icons used in my page are 50px in height, so let's resize them to the correct size.

I'm using imagemagick's mogrify for this.

`$ mogrify -resize x50 -format webp *.svg`

```
./css.webp 562
./c.webp 588
./c++.webp 712
./docker.webp 596
./git.webp 502
./go.webp 482
./nodejs.webp 578
./postgres.webp 678
./python.webp 478
./rabbitmq.webp 404
./react.webp 800
```

WOW! The average here is around ~500B, with some even being 6.8x and 13.8x smaller, while most being 2-3x smaller.

The first time I saw this I couldn't believe my eyes. All my life I thought that SVGs were amazing, small, efficient... 
It's great to see that the image compression world has come this far.

These are insane gains, let's see what would happen for favicons, which are 16px

```
$ mogrify -resize x16 -format webp *
$ find . -name "*.webp"  -exec ls -lh {} \; | awk '{print $9, $5}' | sort

./css.webp 204
./c.webp 196
./c++.webp 226
./docker.webp 190
./git.webp 186
./go.webp 160
./nodejs.webp 178
./postgres.webp 206
./python.webp 192
./rabbitmq.webp 164
./react.webp 184
```

These are spectacular gains. The react icon was 60 times smaller!

In practice this is not very meaningful. You only have one favicon and 800 bytes are not very significant.

But if it happens that you're sending a large quantity of icons that might start to matter, it's all about the scale.

> But Ardi - what if you minify the SVG? 

You're right! Let's try to optimize it using [svgo](https://github.com/svg/svgo)

```
$ svgo .


Processing directory '.':
c.svg:
1.359 KiB - 31.3% = 0.935 KiB

c++.svg:
1.547 KiB - 33.3% = 1.032 KiB

git.svg:
0.687 KiB - 20.6% = 0.545 KiB

go.svg:
1.64 KiB - 16.8% = 1.364 KiB

css.svg:
0.462 KiB - 13.7% = 0.398 KiB

docker.svg:
1.375 KiB - 9.2% = 1.248 KiB

nodejs.svg:
1.606 KiB - 15.4% = 1.359 KiB

postgres.svg:
4.212 KiB - 10% = 3.789 KiB

rabbitmq.svg:
0.728 KiB - 0% = 0.728 KiB

python.svg:
1.081 KiB - 9.7% = 0.977 KiB

react.svg:
10.592 KiB - 16.6% = 8.836 KiB
```

Well, that's underwhelming. What if we gzip them? Most traffic usually gets gzipped to save bandwith anyways!

(webp of 50px)
```
./css.svg.gz 276
./css.webp.gz 372
./c.svg.gz 528
./c.webp.gz 400
./docker.svg.gz 668
./docker.webp.gz 389
./git.svg.gz 321
./git.webp.gz 360
./go.svg.gz 564
./go.webp.gz 299
./nodejs.svg.gz 747
./nodejs.webp.gz 367
./postgres.svg.gz 2,0K
./postgres.webp.gz 421
./python.svg.gz 545
./python.webp.gz 397
./rabbitmq.svg.gz 454
./rabbitmq.webp.gz 295
./react.svg.gz 4,1K
./react.webp.gz 406
```


It's clear that for icons SVGs are bigger than raster images.
However they still have their uses. Mainly CSS animations and larger background images. 
If you're doing this SVGs are a fantastically flexible tool.

## Conclussion

We are engineers at the end of the day. We should understand the trade-offs of the tools we use. 

Most of the time you won't even care about the size of your icons. But if you are, perhaps because you're using a CDN and were considering using a tool such as svgo I hope that at least you consider checking the size of the rastered image.