The Road to SVG and Custom Elements in Clarity Icons

From Font Awesome to the next most-awesome-thing to happen to your icons, this article will talk about Project Clarity’s winding path to its own icon system. It will also give you a behind-the-scenes look at the research we did to create Clarity Icons.

In the beginning: The awesome and not-so-awesome

When the Clarity project started out, our team was focused on delivering a design system composed of UI components that were useful and easy to adopt. Initially, Clarity’s iconography was supplied by the ubiquitous Font Awesome library. But we hit limitations with tying our visual identity to an icon system that was designed outside of Clarity as our set of components evolved.

The strokes in Font Awesome were thicker than our typography, meaning the icon glyphs dominated the text in many cases. The aesthetic of the icons also looked mismatched as our visual style became more opinionated and concrete. As a design system which primarily supported VMware products, we also found that we needed imagery specific to our business’ use cases.

This meant we needed icons that third party icon fonts did not provide. To complicate matters further, our applications rarely used more than 12% of Font Awesome’s icons. We were loading hundreds of glyphs to use somewhere between 10–20 of them. This constituted an inefficient use of our resources, loading multiple files in most cases only to use a small fraction of their content. It also created maintenance issues with having more than one source of truth for our iconography.

The choice became clear that the Clarity team would need to provide their own set of icons that complemented the visual design of Project Clarity.

Our first evolution: SVGs as backgrounds

To maintain the ease-of-use that made Font Awesome so convenient, our first icons were delivered as SVG backgrounds. This allowed us to generate and bundle the icons with the CSS and was a painless transition for our end-users.

Before — With FontAwesome
<i class=“fa fa-check”></i>
After — SVGs as background images
<span class=”clr-icon clr-icon-success”></span>

Using SVGs as base64 background images worked well until our icon library began to grow. Our teams needed to have glyphs in different colors — white icons for dark backgrounds, green icons for success, and red icons for errors.

The problem with our “SVG as backgrounds” approach was that each variation required a completely new icon to be generated as a base64 image in our CSS package.

As you can imagine, this was not scalable and would penalize all of our users with a hefty CSS download, even users who didn’t want to use our icons.

Shortly after putting Font Awesome behind us, we found ourselves needing to evolve one step further.

Photo by Joshua Earle. Courtesy of Unsplash.com.

Considering options and requirements

The Clarity team wanted to explore all of our options in this next phase because we knew whatever we decided would introduce a breaking change. We maintain a design systems used by dozens of products across VMware and aspired to become an open-source project available to teams across the globe. We have always taken the stability of our library seriously and tend to think long and hard about changes to our codebase that introduce work for our end-users.

Because of this, we knew that we needed to commit to an icon system. We could not change our approach every few releases. We needed to weigh our options, choose a path, and stay on course for a very long time, if not indefinitely.

To help us make this choice, we identified several requirements:

Opt-out. While we hoped that our icon system would be compelling, we believed that Clarity users who opted out should not be unduly penalized. We agreed that it should be easier for people to use Clarity Icons with the design system, but users should not be forced to download a huge set of SVGs or an icon font that they did not plan to use. Opting out needed to be an option.

Sizing. Our research showed us that icon fonts and the various flavors of delivering SVGs yielded better and worse results when scaling icons down. We also found quirks in scaling icons up and dealing with positioning inside of containers. We wanted to make sure we chose an approach that didn’t hoist this kind of pain onto our users.

“Badging” an icon

Multi-colored. Additionally, the team did a heuristic analysis of what products needed from our design system’s iconography. One of the most common requirements was badging. Badging required an icon to support at least two colors. We needed an icon system that would allow the use of multiple colors within the same glyph without a lot of hassles or brittle code.

Interactive patterns. In addition to supporting multiple colors in one glyph, our users also needed to be able to add interactivity to the icon set. This meant we needed a system that made animation, hover, and click effects easy to implement — preferably through custom CSS or by using classnames included with the Clarity Icon library.

Extensibility and scale. We needed to be able to extend our set of icons to ridiculous numbers without a negative impact to our end users. We also wanted an easy way for users to add custom icons to our icon system so that applications could be built from one source of truth, instead of several icons in one icon font, still more in an image sprite, and another group of icons in a separate font.

Future facing. In the interest of full disclosure: yes, we did look at CSS sprites! There are some Clarity-based applications that use them. But it’s already clear that the industry is moving towards vector graphics for icons. One thing the Clarity team wanted to do was propose a solution that embraced the future. We did not want to introduce an icon system that saddled our users with an antiquated approach right out of the gate. We wanted Clarity Icons to be as cutting edge and as forward thinking as it could be, even if it meant short-term pain for our development team with packaging (or writing) polyfills and supporting legacy browsers.

Revisiting SVG as backgrounds

With our intentions illustrated above, let’s take a look at how “SVG as backgrounds” measured up:

✕ Opting Out: This was not an option unless users recompiled Clarity’s SASS files to strip out the base64 backgrounds.
✔︎ Sizing: This approach performed well in this regard. The background would size to its container using the `background-size: contain` CSS style. It was also SVG-based so it looked good at small sizes and on different form factors.
✕ Multi-colored: This was doable but it required generating a new SVG background for every color combination. So “doable” but not scalable.
✔︎ Interaction and animation: In terms of very basic interaction and animation, “SVG as backgrounds” worked fine. But depending on the desired effects, it might require additional versions of the SVG.
✕ Grouping and scale: While the base64 images could be delivered in separate SASS files, it would be a pain for Clarity users to strip them out. Scale was also a concern because we were looking at a matrix of possible color variations against stylistic variations like outlined and solid icons.
✔︎ Future outlook: While “SVG as backgrounds” was not the right choice for Clarity, it is a good option for an application that has a well-defined use case for icons. It is vector-based and easy to work with. Our challenge with it grew from needing our icon system to be packaged with Project Clarity and the requirement that we support many unknown use cases to deliver a flexible icon system.

Punchy select boxes! Not to call anyone out. But PUA conflicts are going to be a source of tremendous hilarity over the next several years. Taken from my iPhone about a month ago.

Icon fonts: It’s not you, it’s us

Our first alternative exploration was, of course, icon fonts. Icon fonts have been going strong for at least eight years now. They are vector-based and generally easy to work with. Everyone on the team was familiar with using icon fonts like Font-Awesome and icon font generators like icomoon. Our intent was to test if this approach met our requirements.

✕ Opting Out: I will preface this by saying this is usually not a problem. But the Clarity Project tries to deliver an encapsulated version of its look and feel by bundling the fonts it uses into the CSS. Good or bad, this gives our users one less thing to worry about accompanied by the negative of making it a challenge for users to opt out without recompiling the SASS.
✕ Sizing: Creating a font is a very specialized skill set and doing it properly requires a good deal of know-how, experience, and tools beyond the standards of Sketch or Illustrator. Even well-designed icon fonts can present challenges with baseline alignment and blurriness at smaller sizes. We encountered this when we created an exploratory icon font using our icon glyphs and icomoon.
✕ Multi-colored: The immediate rebuttal here is “stack icons”. But stack icons did not get a thumbs-up from us for a variety of reasons. First, it meant we had to introduce various bits of these icons into the UTF-8 PUA which was already strained across form factors. Second, positioning at scale was tricky and fraught with misalignment. And third, styling these individual layers of iconography meant layers and layers of very brittle pseudo-selector code in the CSS.
✕ Interaction and animation: The icon font was capable of very basic animation and interaction. Anything more complex required a perfect storm of CSS styling, positioning, and properly sized glyphs. For us, it was a house of cards and felt frail and inflexible.
✕ Grouping and scale: This was a “no” that owed more to our delivery than a limitation of the technology. The easy answer is that users could load separate CSS files for each icon set. But this was not a good answer for our situation because we bundle our fonts as base64 in the CSS. Additionally, it would require us to manage the PUA of our sets diligently to avoid conflicts. Ultimately, we could not guarantee that our end-users would not use their own icon fonts to supplement ours. In this spirit, the team preferred to stay away from PUA altogether.
✕ Future outlook: Icon fonts are not going anywhere. But neither are CSS sprites. As SVG-based icons become easier to use, we believe SVG-based iconography will be viewed as the preferable solution. Then again, wingdings are still a thing.

SVG references in the <use> tag

Another approach we examined was inlining SVG with the “use” tag. This would allow us to store our SVGs in one location and reference them anywhere else we wanted to. The only catch was it required us to insert large SVG files in the DOM somehow. While not as big of a requirement for a single-page application using Clarity Angular, this seemed a heavy-handed for other use cases — especially if we were talking about a page that only needed two or three of the icons in the set.

Additionally, we found SVGs in the “use” tag to be finicky with fills, strokes, and shapes. With this approach, we found our CSS selectors could not really drill-down into the SVG. Our options were limited to hacks using the “fill” and “currentColor” styles. This would have been fine for a smaller set of icons with clearly defined functionality and a developer who was well-versed in these hacks.

But it wasn’t going to work for us because our framework, by definition, needed to be flexible.

✕ Opting Out: While simply not loading the SVG file with the icon “defs” in it is the most obvious task in opting out, Clarity users would also have had to locate and remove `use` tags from our templates. In a large application, this was not viable.
✔︎ Sizing: SVGs via the `use` tag could be sized up and down easily. Being SVGs, they were clear at very small sizes and across form factors. But we did encounter problems when using them inline, alongside text. This approach would have required effort to align the icons to the text baseline, in some cases we found this effort was not broadly applicable.
✕ Multi-colored: This was a “yes and no” for “use” tags. “use” tags could handle the bare minimum of this requirement. But it was such a chore to navigate fill and currentColor stylings that we believed this approach fell short in this regard.
✕ Interaction and animation: We found the implementation of our sample animations and interactions to be clunky and overly complex. There was one interaction that never worked the way we wanted it to in our exploration.
✔︎ Grouping and scale: This approach allowed us to deliver icons in sets that users could choose to include or remove as they needed them. This was good, although it put an added responsibility on our users to include SVG files in their DOM. It also meant that we needed a very clear strategy for naming conventions for these icon sets to avoid naming collisions with HTML IDs both across sets and within the DOM.
✕ Future outlook: Of the three most popular approaches for using SVG icons, this is the one that we projected as having the weakest legs. The control over the SVG is extremely limited, especially when compared to the challenges involved with the limited styling options. While a valid approach in the short-term, we couldn’t find a reason why anyone would be doing this a half-decade from now.

Photo by Agberto Guimaraes. Courtesy Unsplash.com.

Custom Elements: We have a winner!

Due to the flow of these kinds of stories, one might imagine that the winner of the Clarity Icons Bake-Off was saved for last. And that would be correct.

In the end, the team decided on injecting SVG into an HTML5 custom element. The big downside is that it does require JavaScript to define the custom elements. But the JavaScript aspect also offered an upside in terms of opting out and customization, described later.

One significant advantage of this approach was being able to manipulate SVG in your DOM with vanilla CSS. Disadvantages included custom elements having limited support, especially in legacy browsers, as well as the general inline SVG downside of images loading and not really being cached. Note that last downside hasn’t been an issue for us thus far.

✔︎ Opting Out: Opting out of this approach is as straightforward as not loading the “clarity-icons.js” file in your application. But you can still use the custom element tags “clr-icon” and their corresponding “shape” attributes to alias to any icon font or CSS background image that you would rather use. So a big thumbs-up here for opting out.
✔︎ Sizing: SVG-based. Predictable sizing, as with “SVG as backgrounds”. Yep, pretty awesome here as well.
✔︎ Multi-colored: Because this produces inline SVG, CSS can manipulate the SVG all the way down to individual paths . Every path within an icon can have its own color and even transitions between colors with a simple CSS selector. This is true for the CSS included with the Clarity Icons package, as well as any custom CSS written by end-users.
✔︎ Interaction and animation: Another big win for inline SVG. We were able to accomplish interactions and animations with very simple and readable CSS that were impossible with other approaches.
✔︎ Grouping and scale: Because we include our SVG inside a JavaScript framework, it’s easy for us to manipulate our set of icons, create aliases for those icons, and add or remove icons from the set. There’s an issue with whether or not users will need to download the full set of icons inside the JavaScript. But we are working on that in the hope that we can deliver Clarity Icons with just the icons a user needs.
✔︎ Future outlook: Custom elements are a “thing”. They are part of the HTML5 spec and one day will be available in every major browser. After working with Clarity Icons, we feel strongly that this is the way people will be using icon libraries in the future. Our confidence was bolstered when Font Awesome announced that the pro version of FA5 will offer an “SVG icon framework” that sounds very similar to what we have built with Clarity Icons. We’re happy to be at the forefront of this tectonic shift in how people build iconography in their applications.

Take THAT, icon font! And I even zoomed the browser in on this so I could screen-shot it. This is a hover effect from our icon research, btw. Accomplished with just a few lines of CSS applied to a custom element.

To conclude our Clarity Icons travelogue, here’s a final look at where we started and where we wound up:

Where We Started — FontAwesome
<i class=“fa fa-check”></i>
Halfway There — SVGs as backgrounds
<span class=”clr-icon clr-icon-success”></span>
Where We Wound Up — Clarity Icons!
<clr-icon shape=“success”></clr-icon>

Not too shabby!

Our next article on Clarity Icons will demonstrate the practical benefits of our icon system and how to use it to create your own custom library of SVG-based icons.

Until then, check out our evolving documentation and keep an eye out for bigger, better, and more coming soon.