We recently posted about the font loading solution we use on our websites. Further to implementing this technique we noticed that, on this very site, some of the fonts weren't quite rendering correctly.

Look at the examples below. The font rendering issues were slight but there was a definite problem with uneven character weighting in the Google fonts we were using (Noto Sans and Cabin).

It's particularly noticeable on the crossbars of the capital Hs but you can also see that some of the ascenders are too bold. Capital Ss also show problems where their terminals on the cap line are bolder than their finials on the base line. There is a similar issue with the bold lower case C. Finally, the apices of the lower case Ts aren't really rendering at all!

(Also note that the rendering issues are only obvious in the first paragraph of text and in the bold title. The second paragraph of text appears to be rendering correctly.)

Comparative screenshots demonstrating font rendering
Font rendering issues (left) vs. correct font display (right). Click or tap image to enlarge.

Tying down what was causing this proved tricky for the following reasons:

  • The problems are only apparent on Windows machines
  • The problems are more apparent in IE than Chrome
  • The problems are only apparent with certain font families
  • The problems are only apparent at certain font size/weight combinations

So, to get to the bottom of this we needed to unpick our font loading solution... We use Font Squirrel's Webfont Generator to generate compressed WOFF and WOFF2 files from the original TTFs.

The generator offers three modes: Basic, Optimal, Expert. We'd entrusted it to 'Optimal' and it transpires that this was causing our problems.

Font Squirrel's 'Expert' mode allows you to adjust a whole host of settings. (See below for a subset of these.)

Font Squirrel generator settings
Font Squirrel webfont generator settings

It turns out that the culprit in this instance is Font Squirrel's Truetype Hinting algorithm. Font hinting is a complicated matter, the nuances of which are beyond the scope of this post, however, suffice to say that automating the hinting process via the default 'Font Squirrel' setting proved problematic.

When we set Truetype Hinting to 'Keep Existing' or 'TTFAutohint' our problems vanished.

It's worth noting that we've not seen this issue on any other projects so this setting must only affect certain fonts negatively. However, as a bonus, this change also involves a file size saving for the variants of Noto Sans our website uses. See the comparison below:

Comparative font sizes showing that 'Keep Existing' hinting option results in ~10% saving
Noto Sans font file size comparisons with different hinting options ('Font Squirrel' on the left, 'Keep Existing' on the right)

As such we've now added a config file which includes this change ("tt_instructor": "keep") to our boilerplate repo.

Moral of the story - leave font hinting to the font designer!

Back in February I wrote about a font-loading technique I'd implemented on a new project, but there was a problem with it - the script ran on every page load meaning the browser cache was never used to serve the fonts. There are many variations on the same theme with some using session cookies to determine if it's a user's first visit to the site, but they all come with their own quirks to overcome. After further research and testing I decided that, while not fully supported yet, the most effective and future-proof solution to this issue is not a JavaScript solution, but a CSS one.

Enter our old friend, @font-face

The @font-face rule has been around as long as I can remember but went steadily out of favour as the popularity of FOUT techniques grew. This is because its default behaviour results in a FOIT while the font is downloaded and with the rise of mobile devices on sluggish connections users can be left with a blank page for seconds or even minutes. This is no longer the case thanks to a new attribute, font-display.

Browser support for font-display is growing with the latest versions of Firefox, Chrome and Safari all playing ball. It degrades gracefully for all other browsers, falling back to its default behaviour and, as an added perk, we don't need to worry about users with JavaScript disabled.

Optimising fonts

Here at Go Tripod we use Google Fonts for most projects but in their default format (TTF) file sizes can be much larger than is required. On slower connections this means the web fonts will take noticeably longer to swap with the system fonts and it's best we do everything to deliver these assets to the user as quickly as possible. We use Font Squirrel's Webfont Generator to convert our TTFs from Google into WOFF and WOFF2 formats which often reduces their size by over 50% meaning the time it takes to download them is significantly decreased. This coupled with the font-display: swap; attribute means we're providing most users with a superior experience which doesn't rely on JavaScript, falls back gracefully and will soon be supported by all major browsers.

One of the first things I decided to tackle as part of my recent work on website response times, assuming it’d be a simple process, was render blocking web fonts. Little did I know I was opening up a right can of words (sorry)…

Numerous techniques have been developed over the past few years with varying levels of difficulty, visual effects and results as described in detail here. The two main visual effects that divide opinion are whether to go down the FOIT (Flash Of Invisible Text) or FOUT (Flash Of Unstyled Text) route. There now seems to be a general consensus within the community that FOUT is preferable for UX reasons with most research showing that it’s better to give users something than nothing - this is especially important for users on slow connections and can lead to high bounce rates.

NB: FOFT (Flash of Faux Text) is the new kid in town but I’ve not tried to implement it yet so won’t discuss here.

After some research I decided to go with Web Font Loader, a script born from a collaboration between Google and Typekit to easily load fonts from a variety of services. We want to load this script asynchronously to avoid it blocking page render so the browser will initially display the content using system fonts and apply the web fonts once they’ve downloaded. The example code below is what you’ll need to add within the head to load Open Sans:

<script async defer type="text/javascript">
    WebFontConfig = {
        google: {
            families: ['Open Sans']
        }
    };
    (function(d) {
        var wf = d.createElement('script'), s = d.scripts[0];
        wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js';
        wf.async = true;
        s.parentNode.insertBefore(wf, s);
    })(document);
</script>

One drawback of this approach is its reliance on JavaScript - users with JavaScript disabled will be stuck with system fonts. This is a tiny number of users, around 0.2%, so we can argue this progressive enhancement benefitting 99.8% of users is worth the sacrifice. Of course, if you’re using web fonts that are wildly different to the fallback system fonts loading before them you probably won’t want to use FOUT as the change in style would be too noticeable. In extreme cases this can even lead to changes in layout so, as with all things dev, do make sure you test thoroughly - you wouldn’t want a user on a slow connection to get halfway through a sentence then find it’s moved position!

Grow your business

Find out how we can help

Get in touch