CSS: Loading Custom Fonts

CSS: Loading Custom Fonts

CSS: Loading Custom Fonts

CSS: Loading Custom Fonts

Updated 2 years ago
5 Minute(s) to read
Posted 2 years ago Updated 2 years ago 5 Minute(s) to read 0 comments

There are a number of methods you can adopt for optimizing overall page performance of your website. An area of concern for optimization can often be custom fonts. Modern websites often make use of custom fonts as part of their overall style of design, however there unfortunately comes the performance overhead in loading them. There are number of tricks you can use to ensure that you are loading custom fonts correctly using CSS.

My website uses two custom fonts that were heavily inspired by the likes of Hashnode - a blogging platform for developers. Those fonts are Manrope and Inter, which I personally think make for a great font pairing.

Minification with Font Awesome

Static font assets (such as WOFF2 and TTF) can't be "minified", however if you are using a icon library such as Font Awesome that ships with a custom font for rendering, then it's important to ensure that you are using minification for the CSS asset file that it also comes with (typically fontawesome.css). For example, the CSS file that it ships with has classes for every single icon that is available as part of the font glyph. This is what makes each icon capable of being rendered as part of text (using the <i></i> tag).

Depending on what your tech stack is will ultimately determine what kind of tooling you ought to use for minification. You may wish to consider using one of the following.

  • JavaScript and Single-Page Application Frameworks (SPAs)
  • PHP and SilverStripe

Preloading JavaScript Libraries

Font Awesome ships with a supporting JavaScript library that will automatically load the correct icon as a fallback, if the user's browser does not support any of the underlying static assets (including .ttf, .eot, and .woff2). If you want to begin loading the supporting JavaScript library asynchronously, you can use the following code snippet.

<link rel="preload" href="/js/fontawesome.min.js" as="script">
<!-- ... -->
  var usedLaterScript = document.createElement('script');
  usedLaterScript.src = '/js/fontawesome.min.js';


Typically most systems make use of the True-Type Format (TTF) for font glyphs that are used system-wide. This is perfectly fine for local usage on each system, but unfortunately comes with added baggage of irrelevant meta data used solely for system installation, when loading static assets over the web. WOFF2 was developed to address this by ensure that compression was taken into account, and that additional metadata originally intended for local system installation was removed.

Blocking Resources

When developing web applications, you want to ensure that you defer loading non-critical resources otherwise this will heavily impact your First-Contentful Paint load times. "First-Contentful Paint" is the metric used by most web benchmarks for indicating how long it takes for the browser to load all critical static assets, in order to begin rendering elements on screen.

Ideally you want to ensure that the browser is rendering your website in as little time possible, with perhaps the caveat that some styling or CSS classes will be loaded after elements have begun to render to the page.

Prioritise Loading Custom Fonts (Asynchronously)

Custom font assets should typically ahead of most static assets on your website. To ensure that this happens, you must declare a <link> tag within the head of your page with the following attributes included.

<link rel="preload" as="font" type="font/woff2" href="/resources/themes/portfolio-devlog-theme/fonts/manrope/woff2/manrope.woff2" crossorigin>

Given that the <link> tag can be used for various static assets (including .css and .js files), it's important to identify the asset's type by using the following attributes as="font" type="font/woff2".

Prevent Invisible Text

If you choose to load your custom font asynchronously, you still run the risk of displaying text that will appear as invisible on your page. The reasoning for is simple - the font has not loaded yet, so the browser has nothing to render the text with! Fortunately there's a convenient way around this, and all it requires is ensure that your @font-family declaration in your static CSS file asset is properly declared.

@font-face {
    font-family: 'Manrope';
    font-display: swap;
    unicode-range: U+000-5FF;
    src: local('Manrope'), url('/resources/themes/portfolio-devlog-theme/fonts/manrope/woff2/manrope.woff2') format('woff2');

The above snippet can be declared in the head of a page as part of an inline <style> declaration, or included as part of a static .css file asset.

I'm using my own website here as an example. Pay close attention to the CSS attribute font-display. We're setting the value to swap simply so that placeholder text (and fallback font) is used while the custom font is still being loaded (providing that it can be loaded).

Quoting the exact description from the W3C draft:

In other words, the browser draws the text immediately with a fallback if the font face isn’t loaded, but swaps the font face in as soon as it loads.

Quoted from official W3C draft.

We're also doing three other other additional things...

  • Stating that the browser should avoid loading the custom font if it's already installed locally.
  • Load only a certain character range of glyphs from the font (e.g. latin glyphs).
  • Load the WOFF2 version of the font (where possible), otherwise use WOFF and TTF version of the font as fallbacks if the browser does not support it.