Fun with Inline SVG

Inline SVG is one of those things that I’ve used for years, but never quite taken the time to understand. It’s easy enough to just copy it into an HTML page and hack it to bend it to my will. I’m very fond of inline SVG for icons in web applications for a few reasons

  • It is relatively inexpensive, meaning you can create some pretty icons for image buttons without a heavy download and it compresses well.
  • It scales to any size (except tiny, and what qualifies as tiny depends on how complex your image is, as in you’re not going to have a lot of detail in a pixel?).
  • You can modify it dynamically with CSS or JavaScript.

I’ve seen some alternatives proposed by developers over the years to scratch some of the same itch, but not anything I like as much as inline SVG, for instance:

  • Custom font-based solutions like Font Awesome: the problem with these, for me, is that many enterprises block custom font downloads in group policy, because of very real security concerns.
  • Emoticons – size-wise, these are certainly appealing, you get some nice images for only a character each, and they’re built into the browser, no image download required. But you have a limited set of icons to choose from, and if they don’t have what you need, you find yourself using an image that doesn’t quite match the action of your button, and that can understandably confuse your users. And historically, different browsers used different characters for the same icon, as in they got ahead of the spec. And ultimately, to make everybody happy, the spec often ended up using either character for that image, which is messy.

So I’ll stick with inline SVG, and given that it’s well past time I dug a little deeper into understanding them. This blog post is my attempt to get started with that.

So now that we’re settled on SVG, let’s take a look at some:

This is the format of an SVG file, but you can also copy and paste it directly into your HTML and that’s what inline SVG looks like. This will produce a blog icon that looks like:

And if you’re new to the concept, you’re probably saying to yourself “really, that’s what you want me to put into my nice clean HTML? And I’m supposed to figure out what all that garbage is inside those paths and code that by hand? That ain’t happening.” To which I say, it ain’t happening for me either. But just FYI, it isn’t rocket science either. What you’re defining inside an SVG is lines/curves, generally connected together to form some shape(s), possibly some geometric stuff like circles and ellipses, and properties like stroke (the color of the line) and fill (the inside color of a shape).

And nobody I know codes these by hand. If you’re just getting started with these, you can download tens of thousands of them from the web. You may have to register on a site to download SVG files. You may even have to pay a few bucks to download more than a few of them. You can also produce your own, but you use a vector graphics image editor like Adobe Illustrator. It’s not that hard, lots of Youtube content to show you how to get started.

The next thing we need to talk about is the viewBox property. This property just defines the top/left coordinates of my image inside the SVG, and the width and height of my image. This makes a lot more sense when storing the SVG in a separate file, as it allows you to put multiple images inside a single file, and slice them out much like the mulit-image sprites we’ve been using in HTML since a little before Moses parted the red sea. For inline SVG, I think it makes more sense to always start your image at top/left 0/0 and 1024×1024. I personally like a big canvas, which makes it easier to do fine details on more complex images, and I can always resize them using CSS. In fact, that’s what I’ve already done above, a 1024×1024 image would really screw up the look and feel of this blog post, so I’ve applied the following CSS:

Note that the SVG above has class=”mysvg“, so I just reference that class in my CSS just like I would do with any other HTML element. And I’ve just resized the SVG to 256×256. I can scale it as much as I like with no loss of clarity (within limits when shrinking). For instance, if I change the style to:

I get something that looks like this:

Which is…I think not good is the technical term? For all intents and purposes, this is just a bullet because 4×4 is just not a big enough canvas to adequately show the details of this image. Interestingly though, if you hit Ctrl+ enough times (8 to 10 times) to zoom in the browser, you’ll see that it is still in fact a blog icon, it just can’t convey the details of the image at 4×4. So the detail is still technically there, but at 16 pixels that knowledge is very little consolation.

Now lets look at one more demonstration about the viewBox property. If I change it to viewBox=”512 512 500 500“, I get something like:

Deconstructing the viewBox, the first two numbers say that my image starts at coordinates x=512, y=512, which since my image is 1024×1024, means the dead center of my image. So at best, I can only show the lower left quarter of my image. But I’m actually showing a little less than that because the second two parameters of the viewBox say to only display 500×500 of the image, so I’m clipping 12 pixels off the right and bottom of the image just to make the point. That’s why the rounded corner on the lower right doesn’t look right.

Now you may be wondering why, if we’re only displaying a little under a quarter of the image, the result looks to be about the same size of my original icon. The reason is that we used the same class=”mysvg” as our original image, the only thing I changes was the viewBox. Which means that whatever slice of the image we choose to display, it will be scaled to 256×256 by the above CSS (not that CSS, the one before that).

And if you’re wondering why you need to know all these details about the viewBox, the answer is because for inline SVG, you really need to specify a viewBox. For instance, If I take the same SVG but remove both the class and viewBox properties, I get:

But I really don’t know what you’re seeing above, I only know what it looks like in my Edge Chromium browser, which isn’t great. Somehow, it’s decide that my intent was to display it with viewBox=”0 0 300 150“. Somehow I don’t see it as likely that 300×150 is some default from the spec. And it isn’t calculated by my paths, because it’s clipping most of my image. So I assume with no viewBox, what you’ll see is going to be pretty browser specific and you can’t count on a sensible decision by the browser (hehe, that’s an oxymoron if I ever saw one).

Also, I gather, if you don’t specify a viewBox, you can’t count on CSS scaling to properly work on all parts of the image.

Finally, the reason it needs to be inline SVG is because if the SVG is read in from a file, the individual parts of the SVG are not part of the DOM, so you can’t apply CSS to them.

You can also specify things like the stroke and fill of the SVG in CSS, which changes the color of the lines and the color of the fill area respectively, so if I add:

I get something like:

Now that’s a blog icon. Uhh, ahhh…color! Pretty exciting, eh?

Now, how do I get that same image in a page twice. You could do:

And you get:

That works, but it’s pretty awful. Say you’re coding some social media type app and you want to add a like button. Ten posts to a page? Ten like buttons, each repeating the entire SVG from scratch? That’s not a great solution. That’s where symbol comes in. You can do:

Symbol just lets me encapsulate and name some part of an SVG. I can then use that part by using a use element and referencing the symbol by name. I can use this to reuse the same paths within a given SVG, or I can reference the symbol in a totally different SVG, as I’ve done here twice. In this case, I put a different class on each, so I get two different colors just like above:

Now we’re talking.

Here’s a more complete example:

This example just uses everything I’ve talked about in this post to produce 6 social media icons in 3 different sizes, like so:

That’s about all the fun I can have with inline SVG in a single blog post. More accurately, that’s about all I know on the subject. As I discover more, I may write additional posts and turn this into a series.

References

Leave a Comment