Sign In

Header image for CSS styleable, vector based icons

CSS styleable, vector based icons

Posted on April 15, 2015


Tags: css, front-end, html, javascript, user interface, video player

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.

In 2014, Blue Billywig introduced it's new Video Player, Player 5. Player 5 set out to replace the two old players made in Flash and HTML, one of these players was served to the end-user based on what their device supported. The new player was built fully in Javascript, HTML and CSS, and featured a Flash 'head' to display video on old browsers.

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:

CROSS-PLATFORM
The entire player will be used on every platform, fallbacks to older technology should be avoided.

COLOURABLE
Our customers can give the player and its icons every color imaginable, so our solution needs to be programmatically colourable.

RETINA SUPPORT
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.

IE8 SUPPORT
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.

Searching for a perfect solution

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.

SVG

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.

SVG images support

Dynamically rendered images

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.

Font-based icons

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.

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.

Icons
SVG images

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:

  1. @font-face {
  2.         font-family: 'bb-icon';
  3.         src: url(data:application/x-font-ttf;charset=utf-8;base64,<...>) format('truetype'),
  4.         url(data:application/font-woff;charset=utf-8;base64,<...>) format('woff');
  5.         font-weight: normal;
  6.         font-style: normal;
  7. }
  8. .bb-container [class^="bb-icon-"], .bb-container[class*="bb-icon-"] {
  9.         font-family: 'bb-icon';
  10.         speak: none;
  11.         font-style: normal;
  12.         font-weight: normal;
  13.         font-variant: normal;
  14.         text-transform: none;
  15.         line-height: 1;
  16.         /* Better Font Rendering =========== */
  17.         -webkit-font-smoothing: antialiased;
  18.         -moz-osx-font-smoothing: grayscale;
  19. }
  20. .bb-container .bb-icon-loader-1:before {
  21.         content: "\e617";
  22. }

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:

  1. if(<IE8>){
  2.         var cachebuster = (new Date()).getTime();
  3.         this._$wrapper.append('
  4.                 <style type="text/css" class="bb-fonts">
  5.                         @font-face {
  6.                                 font-family: "bb-icon"; src: url(<server>/bb-icon.eot?'+cachebuster+'");
  7.                         }
  8.                 </style>
  9.         ');
  10. }

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.

icons in player bar

Future work

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.

Author Blog author avatar

Blue Billywig


Author Blog author avatar

Blue Billywig


 

Other blog posts you might like...

Achieve your goals with video

Want more information on technical development? Get in touch.

Ph +31 (0)  35 8 20 02 80  | email contact@bluebillywig.com | Contact form below

Fields marked with * are required

We use cookies to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media and analytics partners who may combine it with other information that you’ve provided to them or that they’ve collected from your use of their services. You consent to our cookies if you continue to use our website. Read moreOK