Aug 17 2017 | Javascript Web fonts

Handling FOUT in Typekit by caching web fonts in local storage

If you're using Typekit for your web fonts you've probably run into issues with the flash of unstyled text (FOUT) or flash of invisible text (FOIT) on page load.

Certain browsers hide text entirely until web fonts finish loading (FOIT). This delays the page load and can keep users waiting longer or indefinitely. We want to avoid this.

More modern browsers prevent stylesheets, injected by JavaScript, from blocking page loading, following the HTML5 spec. The content is no longer blocked but the FOUT on every load is still not a great experience.

Using a combination of the ‘advanced embed code’ and a cool plugin called Typekit cache we can store the web font in localStorage. We will see FOUT on the first load but all other page loads will look great. I think this is a good compromise.

Use this code in the <head> of your page. Remember to replace the xxxxxxx with your typekit ID and keep the two parts seperated by individual <script> tags:

<script>
//Typekit cache
!function(e,t,n,a,c,l,m,o,d,f,h,i){c[l]&&(d=e.createElement(t),d[n]=c[l],e[a]("head")[0].appendChild(d),e.documentElement.className+=" wf-cached"),function s(){for(d=e[a](t),f="",h=0;h<d.length;h++)i=d[h][n],i.match(m)&&(f+=i);f&&(c[l]="/**/"+f),setTimeout(s,o+=o)}()}(document,"style","innerHTML","getElementsByTagName",localStorage,"tk",/^@font|^\.tk-/,100);
</script>
<script>
//Typekit advanced embed code
  (function(d) {
    var config = {
      kitId: 'xxxxxxx',
      scriptTimeout: 3000,
      async: true
    },
    h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
  })(document);
</script>