Embed SVG Icons in HTML with PHP
Just a way to use SVG on the web
I have been using the font awesome web font for the last few years to add small inline icons here and there on this site, such as the arrow next to "Read the full article" text. It has been working quite well but I found that the style of the icons looked a bit dated and started looking for an easy way to use individual SVG icons instead. Turns out that even in 2021, the question how to best add SVG icons to a website is still answered with "it depends". I found that using some server-side help from PHP gave me good results. Read on for details.
TL;DR: Jump to the solution.
Goals
We obviously want to keep things as simple as possible while maintaining flexibility, and make sure that the end user gets a good experience. So my requirements boiled down to this:
- Should be able to style the icons with an external style sheet
- Ability to select any icon, not having to pick from a fixed set of icons, e.g. Font Awesome
- No complicated workflow, no new tooling - just add the SVG and reference it
- Easy to use in code - just specify the name of the icon and that should be enough
- Icons should display quickly and without any initial flicker
Technical options
So in order to display an SVG, we could use several options. The ones I considered were the
Option 1: img tag
Using
<img src="/content/images/search.svg"/>
And you should end up with:
That seems fine at first, it works just like adding a regular jpeg or PNG. However, styles need to be embedded in the SVG itself, external style sheets have no effect. So we cannot, for example, easily set the color of the icon to the current color of the text. And that's the reason the icon above is black instead of using the color of the text. So no dice.
Option 2: object tag
Similar to img, you can use object just like this:
<object type="image/svg+xml" data="/content/images/search.svg" class="logo"></object>
Result:
However,
Option 3: Javascript
Using a library such as svg-inject, we can use the
Option 4: Inlining
So we end up with inlining as the only option. With inlining, the SVG code for each icon is simply added to the HTML itself. This enables styling using an external style sheet, and since the SVG is delivered with the HTML, there is no additional requests to load the icons - they are delivered instantly. But now we have a new problem: We obviously don't want to copy and paste the contents of the SVG every time we want to use it. PHP to the rescue! (Or whatever you might be using in the backend...)
So with a function such as this, which reads the contents of an SVG file on the fly:
function GetIconMarkup($name) {
return file_get_contents("content/images/$name.svg");
}
We can specify the SVG by file name and put on the page:
<?php echo GetIconMarkup('search') ?>
Giving us:
As we can tell from the look of the icon, the color and size can, and have been, styled by CSS. Nice! And if we need more icons, we can download them, put them in the folder with the rest of the SVG files and just reference them by name. No complicated workflow.
So what about page size?
So inlining the SVGs in the HTML page obviously makes the HTML larger, and also, since the SVGs are no individual files anymore, they cannot be cached by the browser. So how much do the inlined SVGs affect page size? Let's use the start page of this site as an example. It has 9 unique icons at the moment that are used in several places, making it 26 icons in total.
Without any icons: 8,9kB (22,8kB without gzip)
With inlined icons: 10,6kB (33,2kB without gzip)
So gzipped, the increase is around 1,7kB for the 26 icons. The version of Font Awesome I was using previously was 7,4kB gzipped. Granted, Font Awesome would be cached by the browser and reused when navigating around, saving data over time - although the first page load is slower.
Of course, adding more inline icons will make the page grow, but gzip helps a lot especially as long as the same icons are reused. In my case, adding the same icon 1000 times only increased the page size by 4kB, even though it increased by more than 300kB without gzip.
Happy SVGing!
0 Comments
Subscribe to new comments by RSS