Web Fonts, WebFontLoader and Ember

07 February 2016 ·

In this blog I’m doing one not so tricky, though not trivial thing, when I want to set a navigational indicator styling based on the current “active” route.

While using the web fonts, font-based styling can become a challenge, especially if you need to do this on the page load. The problem is that styling will be done based on the first rendered font before your custom fonts are loaded, so the end result will be wrong.

Of course, you might try using timeouts, but this will not work as the long term solution. Basically as always :) My very first attempt was simply delaying styling by using timeouts, but when the network was slow, nothing worked as supposed to, so I decided to go with more robust solution.

Note: This solution will work only if the fonts you’re going to use are from Google Fonts or Typekit and some others, but not so many things are needed to be changed to use other webfonts providers.

First of all you need to get Web Font Loader script, which is “co-developed by Google and Typekit.”

WFL (Web Font Loader) README file says:

Web Font Loader gives you added control when using linked fonts via @font-face. It provides a common interface to loading fonts regardless of the source, then adds a standard set of events you may use to control the loading experience.

After obtaining the script, you need to include it to your Ember-cli-build configuration:

// ember-cli-build.js
...
app.import('vendor/webfontloader.js');
...

Then we need to create a new initializer as we want this to happen only on the initial loading. So we can do this as usual: ember generate initializer webfont-loader.

Then we may define a list of fonts that we can use for our appilication:


// app/initializers/webfont-loader.js

/* globals WebFont */
export function initialize() {
    WebFont.load({
        google: {
            // Here we can define our list of fonts.
            // To know how to use the WebFont loader please
            // check their documentation:
            // https://github.com/typekit/webfontloader
            families: ['Roboto Mono:400,500,700']
        }
    });
}

export default {
  name: 'webfont-loader',
  initialize
};

That is basically it. The result of doing this will be a few events that you can use to do what you need.

Unfortunatelly these events are just simple classes on your <html> element, but it’s fairly enough to do what I needed: to set the width of the “navigational indicator”.

I’m using one more initializer to reopen the Ember.Route class and add more things to its didTransition actions:


import Ember from 'ember';

// this is not the best solution from design perspective,
// although is the easiest and the most comprehensive
var initialized = false;

export function initialize() {
    if (initialized) {
        return;
    }
    Ember.Route.reopen({
        actions: {
            didTransition() {
                let areFontsLoaded = false;
                let page = Ember.$('html');

                // Here I'm setting the styles of the indicator
                let setIndicator = () => {
                    let indicator = Ember.$('nav .active-indicator')[0];
                    let activeLink = Ember.$('nav li a.active')[0];
                    if (indicator && activeLink) {
                        indicator.style.left  = activeLink.offsetLeft + 'px';
                        indicator.style.width = activeLink.offsetWidth + 'px';
                    }
                };

                // And I'm doing this only when the fonts are loaded
                if (areFontsLoaded) {
                    setIndicator();
                } else {
                 // Otherwise we check our <html> tag for wf-active
                    // class which is set when the fonts are loaded
                    let checker = setInterval(() => {
                        if (page.hasClass('wf-active')) {
                            areFontsLoaded = true;
                            setIndicator();
                            clearInterval(checker);
                        }
                    }, 10);
                }

                return true;
            }
        }
    });
    initialized = true;
}

export default {
  name: 'nav-indicator',
  initialize
};

That was a small example of the usefulness of Web Font Loader library and how to put it inside Ember application.

Please let me know in the comments if you have any questions or you have solved this problem in a different way.

UPDATE 20/02/2016: As per discussions in comments and suggestions from Ken and Andrey, I’ve published ember-cli-webfontloader addon to avoid all that headache. You may use it, but anyway, I believe that this post is not just about solving one problem, but for showing you, how to solve one-time problems like that.

Tags:

Might also be interesting for you

Use Elm as a Reducer in Redux

Want to use Elm in your project, but a bit hesitant going cold turkey? In this blog post I'll try to show how you can use the best from both worlds bulletproof Elm logic and ridiculously rich React components library.

Open RSS Reader

I'm starting a new open-source project "Open RSS Reader" that will be modular app so if you don't like the existing clients, you'll be able to quickly build your own. It's gonna be both open source and free to use.

SotM: pet - Awesome Command-line Snippet Manager

`pet` is a simple command-line snippet manager. It allows you to write and store snippets for the command-line, so you don't need to remember all the commands you frequently use in you terminal. It can sync your snippets to the GitHub Gist, so you can always take your snippets with you.

5 Reasons To Give Linux A Try

This time I want to share 5 reasons why I advocate for using Linux whenever I have a chance, and why you should give it a try too.

Comments

comments powered by Disqus