Close search results
Close search results
Part of an SVG icon.

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 img tag, the object tag, using Javascript, and inlining.

Option 1: img tag

Using img is pretty easy. You just create a tag like so:

<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, object has a similar problem like img. It can actually use an external style sheet but the CSS file needs to be referenced from within the SVG file. Since we don't want to edit each SVG before they can be used, this is not good enough.

Option 3: Javascript

Using a library such as svg-inject, we can use the img tag and let the library load and inject the SVG files into the document. So we have the simple usage of the img tag, but we can style it using CSS. Pretty neat! However, there might be a slight delay until the icons show up since they are not delivered with the page. Also, why leave something to the client that the server can do? (OK, that might have been sarcasm.) So that leaves us with...

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!

Part of an SVG icon.
Part of an SVG icon.

Leave a comment





This will just take a second.

Submitting your comment...
Page Theme: Dark / Light
Erik Moberg  2024