SJ (Scott Jehl)

Have It All: External, Styleable, & Scalable SVG

photo of scott jehl profile headshot

By Scott Jehl

It has been a few years since I'd last tinkered with approaches for embedding SVG into webpages, but a nice post making the rounds today prompted me to take a look back at where I'd last landed. While that post cites a few perfectly good ways to include SVG into a page, here I'll demonstrate a 4th approach that I think hits the center of the venn diagram for External, Styleable, and Scalable SVG.

External, Styleable, and Scalable SVG

First, a demo. The SVG below is external (so it's cacheable), styleable, and scalable. Its colors use the global CSS custom properties that are defined in this page below, which could either be shared across icons in the page, or set differently per SVG using CSS selectors.

For demo purposes, I've made the styles above editable (I put a contenteditable attribute on the style block and set it to display: block if you're curious), so you can edit those rules to see that they carry through not only this page but through to external SVGs. This little editable trick has nothing to do with the SVG embedding though, fwiw.

How It Works

Long story short, the svg use element now offers a nice means of referencing SVG symbols, whether they're in the same page or in an external file.

<svg width="100" height="100">
<use href="/sandbox/svgtopia/wrench.svg#icon"></use>
</svg>

In this case, the SVG references the external /sandbox/svgtopia/wrench.svg file, plus a #icon hash that points to a symbol element inside the SVG file that contains our wrench icon, which has an ID attribute of that same name.

<symbol id="icon" viewBox="0 0 390 390">...

In order for the CSS color variables to do anything with the CSS, the SVG file needs to use those same CSS custom properties for its fills and strokes on its polygons and paths (or whatever else you'd like to be configurable). Note that I've used a style attribute that references the preferred CSS custom property first, followed by the fallback color again.

Here's an example:

<polygon points="145.69 300.383 257.48 300.383 257.48 257.422 145.69 257.422" style="fill: var(--svg-color-2,#64C5E5);"/>

Of course, this kind of prep is a little tedious, which is why I think some tooling can make it a little nicer. More on that in a sec.

Anyway, from here you can either style the custom properties across the page for a shared color scheme, or target a specific icon by giving the svg element a selector, eg:

HTML:

<svg class="my-icon" width="100" height="100">...

CSS:

.my-icon {
  --svg-color-1: red;
}

Limitations

While this satisfies most requirements for including SVG in a page, it doesn't work for SVG files that are on an external domain. So you'll need to self-host the SVG file for it to work.

Also, you won't be able to carry those CSS custom properties through to CSS background images, or really most any other means of including SVG in your page. It's totally possible though, to reference the same svg from CSS, but you'll need to be happy with fallback colors in the SVG. (See the Iconoclash demo at the bottom for examples that are prepped to work with CSS backgrounds, as they require even more internal prep to do that.)

Tooling Would Make It Nicer!

When I'd originally started playing with this approach, I made a tool to handle the preparation. It's called Iconoclash and it's been a little while since I last worked with it, but perhaps it's due for an update?

If anyone's interested LMK!

Thanks for reading!

I hope you found this useful and thank you to Micah R Ledbetter for writing the post that led me to get this up on the blog!