I received an email recently asking for assistance with an SVG icon issue. The individual explained that he was working with a lot of icons (about 300, which I would say qualifies as a "system") as images and wondering if there was a way to change these colors with CSS after the fact to accommodate color blind users when the situation presents itself, and if not how to get around adding 300 inline SVG icons to his markup.
So the problem, as I understand it, is that he needs access to the SVG's "innards" to be able to change the fill color, and therefore not having to include twice as many icons as you would have to do with images but also not have bunches of inline SVG code sitting around in his markup.
When you use an SVG as an
img you cannot then go "in" to the SVG and change its fill or stroke with CSS. This would very quickly prove frustrating and inefficient when working with so many icons. Accessing the fill of these icons to change the palette for color blind users, for example, would be impossible and you would therefore need additional images.
A really neat way to go about this tricky icon system issue is to use SVG sprites, as is fairly thoroughly described over at CSS-Tricks.
Let's take a look at how to store each icon just once and then use it multiple times throughout the doc, at times altering its styling with CSS. We'll break down each of the concepts involved in this bit of icon wizardry and take a look at an additional demo to further understand this super mashup taking place.
To take a bit of a step back, sprites are essentially a way of combining multiple images into a single file. A site with multiple images can take much longer to load, and a sprite is basically serving up multiple images as one document, cutting down on server requests.
Some especially neat instances of image sprite use on the web are related to producing animations, like the one in this demo by Simurai which allows you to see what's going on "behind the scenes" as well.
SVG sprites follow this same logic of putting a bunch of images in one document, except the especially beautiful thing here is that SVG is the source file. You can open up your text editor and place all the SVG icons in that one file, separate from the main HTML doc for the project.
We will be including our external SVG sprite doc, so we won't see the SVG shape details in our main HTML. These icons are written inline, exposing all that path and shape data. Let's take a quick look at the heart icon:
<symbol id="icon-heart" viewBox="0 0 1024 1024"> <title>heart</title> <path class="path1"> <!-- Lots of path data written here --> </path> </symbol>
Workspace & Use of Symbol
The use of
symbol instead of
g for grouping the individual icons is especially neat for a couple reasons. It allows us to include the icon without it rendering until it is told to do so through
use and it permits for the specification of a separate
viewBox for each icon, keeping this bit of code in our sprite document and not having to specify this later.
Here is the code associated with calling on the heart icon that is written out above:
<svg class="icon icon-heart"><use xlink:href="#icon-heart"></use></svg>
I also wrote a little book about writing SVG that may prove helpful navigating the syntax and general jargon associated with using SVG inline.
When talking about icon systems we are in practice working with a lot of icons and a general assumption that no one is creating all these icons from scratch. This is where a tool like Icomoon can be a real life saver. IcoMoon is an incredibly useful resource for obtaining and managing SVG icons and even SVG sprite sheets.
Once you have your icons you can download them as an SVG sprite right from IcoMoon, or your can generate this by hand by grabbing the SVG code for each and placing them all within the same
svg element in a text editor (one doc, one svg).
There is also a Grunt plugin that will automate much of this process for larger scale projects.
So we have a basic idea of how to have a bunch of icons without repeating any inline code and be selective with what we want displayed, but what about styling the individual parts of these graphics with CSS?
In the case of the question presented via email, CSS styling was needed on occasion to change the icon colors to accommodate color blind users. Calling on these same icons and adding an additional class will allow us to select this individual icon in our CSS and declare separate styling. A button has been added to the demo below that will change the theme of the second set of icons. This same practice can be made to produce colors better suited for color blindness.
In short, with this approach to icon management we can have multiples of the same icon which is only written once in our external doc, and then style them completely independent of each other.
Depending on how the icons were built (for example, a compound path versus several grouped parts) you may be styling fills, or strokes, or both.
In the HTML of our demo we are linking to an external file containing the SVG sprite (to do this locally outside of CodePen you would use an include of some type). Once this include is made we can reference the icons within the file through the
use element, allowing us to not only access the "innards" of the icon but also keep our HTML from getting bogged down with inline SVG code.
Once we have linked to our sprite document we can begin to call on whichever icons we wish to show themselves.
A Note On Icon Fonts
While there is certainly nothing wrong with using an icon font in these types of situations, you may quickly feel restricted by its limitations depending on the needs of your project. Perhaps the greatest downside of using an icon font over inline SVG is that you cannot add multiple colors to the icon. So, SVG is more editable in that it is the source code for the graphic, so we are able to easily "get inside" and make changes both within the SVG code itself and with CSS. With font icons it's a bit of a "what you see is what you get" situation.
There's also a signifiant accessibility advantage that inline SVG has over icon fonts, but for a more complete breakdown of these benefits you should head over to the Inline SVG vs Icon Fonts Cagematch on CSS-Tricks.
Working with a great number of SVG icons on a large scale project can seem especially complex. We want access to the individual SVG parts as inline would provide us with but also don't want the code for hundreds of graphics being repeated in our HTML. Using SVG sprites, in a sense, supplies us the best of both worlds.
All of this same logic would apply to icons that you created yourself with vector graphic software, but a bit more code cleanup will be required. You will want to use an SVG optimizer such as Peter Collingridge's or SVGO, and be sure to look over this list of potential gotchas when getting inline SVG ready for production (a real time and frustration saver).