Dienstag, 21. Oktober 2014

Probably Don’t Base64 SVG




CSS-Tricks





Probably Don’t Base64 SVG



Perhaps you've heard of data URIs. It's a really nice way of including a resource that would have otherwise been a separate HTTP request. The format that you use in a data URI can vary. Essentially you just tell it what content type it is (e.g. image/png), semicolon, then the data of that file.



Like:


<img src='data: ... '>

or:


.bg {
background: url('data: ... ');
}

For a raster image like a PNG, the data of that image needs to be in base64 format. I'm not a huge expert here, but as far as I understand, base64 is safe for use in something like HTML or CSS because it only uses 64 characters known to be safe in those formats.


On the left, the data of a PNG, which includes characters that have the potential to screw up HTML. On the right, that same image base64 encoded with all safe characters.

Probably better Stack Overflow answer by Dave Markle:


You never know - some protocols may interpret your binary data as control characters (like a modem), or your binary data could be screwed up because the underlying protocol might think that you've entered a special character combination (like how FTP translates line endings).


So to get around this, people encode the binary data into characters. Base64 is one of these types of encodings.


Base64 looks like gibberish, and we often associate gibberish with compression on the web. But this gibberish isn't compression, it's actually a bit bigger than the original because, to quote Jon Skeet on the same Stack Overflow thread:


It takes 4 characters per 3 bytes of data, plus potentially a bit of padding at the end.


I'm not sure how gzip factors into it though. But what I'm getting at here is how SVG factors into this.


You can use data URIs for SVG too.


<img src='data:image/svg+xml; ... '>

.bg {
background: url('data:image/svg+xml; ... ');
}

For SVG, you don't have to convert the data into base64. Again, not an expert here, but I think the SVG syntax just doesn't have any crazy characters in it. It's just XML like HTML is, so it's safe to use in HTML.


You can leave the encoding in UTF-8, and drop the <svg> syntax right in there! Like this:


<img src='data:image/svg+xml;utf8,<svg ... > ... </svg>'>

.bg {
background: url('data:image/svg+xml;utf8,<svg ...> ... </svg>');
}

So because we can do that, and we know that base64 often increases the size, might as well do that right? Yep. As a side benefit, the <svg> syntax left alone does gzip better, because it's far more repetitive than base64 is. Say you wanted two versions of an icon, one red, one yellow. You can use the same SVG syntax duplicated just change the fill color. Gzip will eat that for breakfast. Credit to Todd Parker for that tip, and that's also the approach of Grunticon, which data URI's SVG in UTF-8 into CSS.


A Test


To test this out, I downloaded three SVG icons from IcoMoon.



cog.svg - 1,026 bytes

play.svg - 399 bytes

replay.svg - 495 bytes


I ran them through SVGO just so they are nicely optimized and kinda ready for use as a data URI (whitespace removed, although I guess not strictly necessary).


cog.svg - 685 bytes

play.svg - 118 bytes

replay.svg - 212 bytes


Then I ran those through a base64 converter.


cog.svg - 916 bytes - 133% of the original size

play.svg - 160 bytes - 136% of the original size

replay.svg - 283 bytes - 134% of the original size


So that makes sense, right? If it's 4 characters for every 3 bytes, that's 133% bigger, with the variation coming from uneven lengths and thus padding.


Anyway, maybe this is all super obvious. But it just seems to me if you're going to use a data URI for SVG there is no reason to ever base64 it.


Props to Matt Flaschen for his email a few months ago that highlighted this issue for me.




Probably Don’t Base64 SVG is a post from CSS-Tricks








Keine Kommentare:

Kommentar veröffentlichen