Web Fonts and Javascript Position Offsets

Funny things can happen to your Javascript effects when you use web fonts. Especially when you are dealing with object positions at load time. I had an issue myself installing web fonts on this site, and thought I would post the solution here in case anyone else runs into a similar problem.

Let me first make it clear that I am not trying to discourage developers from using web fonts. Like any web designer out there, I am very excited about the possibilities that services like Typekit have made available to the masses. No longer are we stuck with Georgia and Verdana as our only font options for every site. Web fonts are fantastic! I'm glad we cleared that up, let's move on.

Moving on

I recently posted a tutorial on using Javascript to make an object follow the position of the mouse. One day I noticed that in my demos the object was no longer underneath the mouse. Instead there was a gap. If I moved the demo further down on the page, the gap between the object and the mouse got bigger. What had changed to cause this offset when the page worked fine a few days earlier? I hadn't changed any of the code.

The answer was web fonts. But, you might ask, how could something so wonderful as web fonts do something so horrible as breaking all of your innocent Javascript math? Whether or not you are actually asking that, I'll give you the answer. It was actually pretty obvious once I sat down and worked it out. So here you go —

Web fonts breaking DOM object positions explained

The code I used to store the object positions was executed on the DOM load event. Technically this is the moment that the browser has loaded its content and rendered the page. This is when all of the object positions are supposed to be final. Except that when using web fonts, the page isn't finished rendering yet.

Web font loading happens after the DOM has completed loading. Once the fonts have finished loading, the text is re-rendered using the downloaded fonts. This is why on some sites you see the text shift around shortly after the page has loaded.

Since I was getting object positions before the fonts were loaded, the positions I saved were not valid. They were not the positions of the objects once the fonts were loaded and the text had finished moving. And because the shifting gets larger the further down the text you go, the offsets in my demo were bigger the further down the page I placed it.

So what is the solution?

Well one way to fix it would be to continuously get the object positions. This way the position you have will always be correct. The problem is that constantly polling the browser for current object positions places an unnecessary load on the browser and can slow your scripts.

Thanks to the hard-working guys at Typekit, there is a better way. Instead of constantly polling for the current positions and offsets, you only have to get them once, right after the web fonts have finished rendering and all of the object positions are final. Typekit makes this easy with its font event callbacks.

To fix my demos, I simply added an event handler that updates the object positions once the web fonts are rendered. I've included a snippet of the code so you can see how it works.

// Javascript to execute when fonts become active
try {
  Typekit.load({
    active: function() {
      offset1 = $('#mouse-position-demo').offset();
      offset2 = $('#mouse_follower_demo').offset();
    }
  })
} catch(e) {}

For more info on these events and other things you can do with them, read Typekit's article discussing their callbacks. If anyone has their own tips in using Javascript and web fonts together, please post them in the comments.

This entry was posted in Javascript, Tips, Web Design and tagged , , , , . Bookmark the permalink. Follow any comments here with the RSS feed for this post.