Use Icons Without the Overhead of Loading an Entire Library

I recently started to look for an icon library to add to my arsenal of tools for web UI development.  What I wanted was a simple and light weight widget that allowed me to include only the icons I am interested in using and nothing more. I like my apps small and to include only the code that it actually uses, so the suggestion that I should just “include” an entire library in order to be able to use an icon is not one that I will entertain.  As a matter of fact – I bet that most app pages use at most a handful of icons – so why do I need to get them all again?

What I needed was a library that exposed all of its icons as single images – preferably in SVG format – so that i could just add them to my projects as singletons and then use them in my markup as needed.  Better yet – create a widget that uses that single icon and then be able to reuse it across my markup without having to duplicate code. It was around this time, that I see this tweet come across my timeline:

When I took a closer look at this library, it included exactly what i needed – all icons were available as SVG. And, how interesting was this: the author of the library had a open Issue asking for help in creating a reusable widget…

boxicons-issue-6

Too much of a coincidence? Yea, I think so too.  And too inviting as well 🙂

After a few exchanges with the author, we agree on an implementation and I submitted a pull request with the contribution to that project that added a Custom Element (aka: a native HTML element compatible with any framework or library 🙂 ) which allows for the use of icons without incurring the cost of having to load the entire set of icons.  Its pretty simple to use.

Add the script to the end of your HTML document, inside of the body tag and then freely use the box-icon element where ever one needs an icon:

box-icon-example

Boxicons seems like a great option for what I was after and the number of icons has more than doubled since I last made the contribution. It is now my “goto” library for icons.

How it was done

The widget is built as a native Web Component, thus its usable in a declarative way in any framework available today.  Its API – all driven by HTML element attributes – supports control over size, color, rotation, flipping as well as to apply animations. Internally, here is the way it works:

  1. When the name is defined, it will create a new HTTP REST request to retrieve the SVG image from the Content Delivery Network (CDN). The image is cached once it is retrieved for the first time
  2. Once retrieved, the SVG is written directly to the widget’s body
  3.  Because the image is SVG, it can easily be manipulated and thus options like “color” are simply applied (as CSS rules) to the SVG image
  4. The Widget provides static class members that define the CDN’s URL, thus supporting extensions where content might be served from different locations outside of the default
  5. The Widget exposes the method used to retrieve the image, thus providing an additional customization point – example: in cases where the image might have been bundled (webpack) with the app and it just needs to return the SVG markup rather than make a network request for it

Overall, I’m very pleased with how it has turned out and it is now part of my toolset.

Take away

With every project I work on, I look for opportunities where I can create something that solves a common problem in a way that it can be reused again in other projects. With this one contribution to Boxicons, I came up with a wrapper that will automatically load the Web Components polyfills prior to executing the code that depends on it.  It looks like this:

;(function(init){
    if (!('customElements' in window)) {
        var script = document.createElement("script")

        script.type = "text/javascript";
        if (script.readyState){ // IE
            script.onreadystatechange = function(){
                if (
script.readyState == "loaded" ||
script.readyState == "complete"
){
                    script.onreadystatechange = null;
                    init();
                }
            };
        } else {
            script.onload = function(){
                init();
            };
        }
        script.src = '//cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.0.2/webcomponents-bundle.js';
        document.getElementsByTagName("head")[0].appendChild(script);
    }
})(function(){

  //...widget code here

});

Because I use it so much, I have also created a webpack plugin for it – web-components-polyfill-webpack-plugin , which will also apply an ES5 polyfill if needed (aka: Internet Explorer). I will primarily use this to publish Web Components directly to NPM in a “ready to use” state.

What is Next

So I now have a small little widget that allows me to efficiently use icons from a very large library… but, in some use cases, I might need icons from other libraries in order to match the styles being used by the page that will host a given widget. My goal at some point soon will be to take the widget I created for Boxicons and make it work with other libraries that also provide their icons as SVG – and believe me there are many and I predict that many more will arise as SVG becomes the go to standard for icons and images on the web.  So for example, if using Material UI, I would like to use one of its icons like this:

i-con-example

Thanks for reading!

/Paul

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s