I have seen in many places this year the advice to not use pixel based images or fonts any more for symbols and icons. Reasons behind this general shift: size, number of download and smooth sizing.
SVG seems to be the better choice.
Regarding the size, caching is a quiet useful option that reduces repeated downloads of static content and this is also true for SVG files.
Here I compare the methods of using SVG integration as there are multiple options but no one-fits-all.
Using the PNG image format is best when using pixel based icons as they can be optimized in size very well and do not have visual artifacts like jpg images. But of course they do not scale smoothly as they are pixel based.
<img src="check.png" style="width:48px;height:48px" />
54 bytes are required to implement the minimal img element in html and another request to the server is required to get the 774 bytes of the image. The size alone is not the problem in this case as it very small but the second request is taking time.
Also all colors are defined inside the PNG file and not in the CSS.
Just switching to the SVG format results in img tags referencing to a SVG file.
<img src="check.svg">
The advantage is the smaller size but also scaling it up will result in good quality. Just zoom in the browser to see the difference.
Also all colors are defined inside the SVG file and not in the CSS.
SVG integrates also directly into HTML elements as a inline-block element so no second download is required.
This approach allows even using the colors from the surrounding html into the svg e. g. by specifying currentColor
as a color on the svg element to use the current text color.
<p style="color:red">
<svg viewBox="0 0 48 48" style="height:48px;width:48px">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="6"
d="M8 24l10 12L40 12"></path>
</svg>
</p>
On the opposite side it is hard to maintain inline svg code that is used in many places. Frameworks that compose html by html fragments can help but there are more options...
SVG offers the feature to define elements in a central place and to use them by references. The definition can be inside the HTML or in a separate file.
The central definition is using the symbol
element inside a SVG definition similar to a standalone SVG file.
<symbol id="add" viewBox="0 0 48 48">
<path fill="currentColor" d="M8 4C5.784 4 4 5.784 4 8v32c0 2.216 1.784 4 4 4h32c2.216 0 4-1.784 4-4V8c0-2.216-1.784-4-4-4zm2 4h28c1.108 0 2 .892 2 2v28c0 1.108-.892 2-2 2H10c-1.108 0-2-.892-2-2V10c0-1.108.892-2 2-2z"/><path fill="currentColor" d="M22 14v8h-8v4h8v8h4v-8h8v-4h-8v-8h-4z"/>
</symbol>
A SVG example of such a file can be found here containing a lot of symbols / icons for IoT devices. (You have to open the source code to view the implementation)
To use the icon a use tag inside the svg use
element has to be used.
<svg class="icon"><use href="./icons.svg#add" /></svg>
This approach fits good for use-cases where many icons are used in many places as the definition taking the most size is only loaded once.
This is a variation of the SVG file referenced in the img
tag so a second request to the server
is avoided by adding the svg code directly using a data link.
It can be base64 encoded but svg can also be used directly when quotes are not used.
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0i ...<cut out>... Lz48L3N2Zz4=" />
In CSS svg data based images can be used as background images:
.back {
background-image:
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path d='M12 12L36 36M36 12L12 36' fill='none' stroke='white' stroke-width='12' stroke-linecap='round' /></svg>");
}
This is not much of use inside HTML and takes more space than the SVG tag used directly but it is an option to include a SVG image in CSS as it is done with the red close symbol at the top.
There is no best solution that fits into all use-cases. Here is the summary in a table.
Format | inline sizes | extra download size | use-cases |
---|---|---|---|
PNG file | 54 bytes | 774 bytes | This is the 'old style' for icons. |
SVG file | 54 bytes | 221 bytes | A direct replacement for the 'old style' using less bytes and scalable. |
SVG inline | 275 bytes | 0 | best for rarely used symbols. |
SVG referenced. | 55 bytes | 221 bytes in shared download | best option when many icons are used many times. |
SVG in data source | 336 bytes | 0 | usable in CSS. |