Icons have always been an important part of an interface. They allow the user to recognize certain actions with only a glance. In this blog, we will look for a complete and closing solution to render css-styleable icons that are supported by older browsers while still looking great on modern retina displays.
A big part of the user interface in the videoplayer exists of icons: Play, pause, volume, subtitles, almost every control uses an icon to label its action. This emphasizes the need for a solid solution, especially given our requirements:
The entire player will be used on every platform, fallbacks to older technology should be avoided.
Our customers can give the player and its icons every color imaginable, so our solution needs to be programmatically colourable.
Mobile devices will also be using the player, and we want to make full use of the high density screens.
When Internet Explorer 8 will be ancient history, things like this will be much simpler.
Perhaps the biggest bottleneck, certainly worth an extra mention.
NO EXTERNAL RESOURCES
The player will be served to almost 10 million users every month, every extra request per player will put significant extra load on our back-end servers.
A big advantage in projects like these, is the available time to experiment with new solutions to find the perfect technology to fit our needs. We have looked up numerous different methods, some very conventional, others very unorthodox.
The first that comes to mind when working with vectors on the web is Scalable Vector Graphics, or SVG. It is styleable with CSS, the vector graphics are razor sharp on mobile devices and they can be loaded via inline HTML. Support for SVG is excellent, with almost no issues in rendering between different platforms, except with a front-end developers' biggest enemy: Internet Explorer. IE8 does [not support](http://caniuse.com/#feat=svg) the vector format at all. Since a workaround will always leave us with a less-than ideal situation, we will look further to another solution.
Another option is to use PNG images (perhaps even a CSS sprite) to display the icons. Most other video players display their entire user interface with PNG icons, but they lack the need for dynamic colors. We can support high-res displays with CSS mediaqueries and the @2x tag, PNG support an alpha channel and the images can be embedded with base64 encoding. Since the icons will not change color after being loaded by the user, we can dynamically build the PNG's on our servers based on the configuration, and embed them inside the player before sending it to the user.
This seems like a viable solution, but it requires a lot of work, both on the front-end and the back-end, and isn't as convenient as doing all the hard work client-side. In our search, we've come across a solution that is close to perfect, and provides a better end result than images.
Icons based on fonts are becoming more and more popular. [FontAwesome](http://fontawesome.io/) is a very good example of a complete vector icon pack that can be styled with CSS and will work on IE8. Fortunately, it is also possible to encode the font with base64, and load it inline in the CSS. Internet Explorer limits the size of the encoded string to [32kb](http://caniuse.com/#feat=datauri), but the extra request coming from IE8 users (less than 1% of the total) will not be notable. All these features conclude in a near-perfect solution to our problem, what remains is the (admittedly tricky) implementation.
All our icons are designed in Adobe Illustrator and exported as separate SVG files. We use the fantastic online [Icomoon](https://icomoon.io/app/) application where we upload all the SVG files. We include IE6 and 7 support and let the application generate our fonts.
We then convert the TTF, WOFF and EOT files to a base64 encoded string, and insert this with the Icomoon CSS into our own CSS file:
As you may notice, we only use the TrueType and Woff files in this CSS. We insert the EOT file for IE8 later, when we detect Internet Explorer:
During testing, we noticed that font-rendering does not work when coming from cache. This is why we implemented a cachebuster to always request the front from the server.
This method of rendering vector-based icons that are (somewhat) styleable with CSS works excellently for our use case. The icons look gorgeous and razorsharp on every device that we've tested, and the customizability is great.
When Internet Explorer 8 will be ancient history, things like this will be much simpler to implement. Until then, we must face the limitations of today and push the boundaries of technologies to create the best experience for our customers, like we did here with 'simple' things like icons.
Recently, a customer notified us about an issue with invisible icons, which caused us to further investigate our icon rendering system on IE8. It turns out, that Internet Explorer features an obscure safety option to disable the use of external fonts. For many users, this will never be a problem, but company ICT policies can cause these issues to exist.
To solve this potential problem, we are planning to build an ultimate fallback 'when all else fails'. First, we will insert an invisible dummy element using height: auto containing an icon. When the icon renders, it pushes the height of the element to something greater than 0. We can exploit this behaviour by requesting the computed element height with jQuery ($.height()), and checking for a value higher than 0. When the element is 0, we can replace all icons with static images that are loaded from the server. This guarantees that the user will always see icons, by checking whether the icon ultimately rendered or not.