Web fonts enable us to have good design, branding, readability and accessibility. Moreover, they would bring selectable, searchable, zoomable and high DPI text. However, with every advantage comes a trade off.
All other parts:
Part 2 use Preload/Prefetch to boost load time
Part 3 JavaScript tips and tricks
People use web fonts heavily these days without realising how much impact it would have on the overall page speed.
This doesn’t mean you shouldn’t use them, just the fact that you should know how to use an optimised font and to how to load to reduce the impact on page load.
Optimising web fonts depends on where you host the font, your web application’s design and back end server, your technical abilities and how far your company is willing to invest in this. But don’t let this hold you from following the techniques I will go through, even a little improvement on overall page load counts towards a better user experience.
Before you start the task, you should find out what fonts are used throughout your website. You can easily find this out using Audit tabs in Chrome DevTools’ network tab and looking at the HTTP requests.
Once in the tab click on the filter icon and look for file extensions like woff
, woff2
, tff
, otf
and so on:
Research shows on average 67% of web pages use custom fonts, with websites averaging between four web font HTTP requests.
Once you figured out how many fonts you are using, you should think about how many fonts you should use. Normally these decisions are driven by UX or design team, but you can definitely have a word with them.
If you are thinking how many is too many, the rule of thumb is that three is crowd and two is the best to stick to.
If you use less fonts throughout your website, not only the number of network requests are reduced, but also the design is more streamlined and consistent.
Unless you have an international website supporting multiple languages, it doesn’t make sense to use all character sets. Choose only what you need and for the languages you use.
Ilya Grigorik a Developer Advocate and Web Perf Guru at Google, explains how you can subset or split web fonts into multiple unicode ranges to deliver only what you need.
You can use the Unicode-range descriptor to specify a list of range values, which can be set out in three different forms:
?
character indicates any hexadecimal digit.To demonstrate the possibilities, this is how you can split the Font Awesome into Latin and Japanese subsets. Once done, the browser would download each subset as needed.
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
src: local('Awesome Font'),
url('/fonts/awesome-l.woff2') format('woff2'),
url('/fonts/awesome-l.woff') format('woff'),
url('/fonts/awesome-l.ttf') format('truetype'),
url('/fonts/awesome-l.eot') format('embedded-opentype');
unicode-range: U+000-5FF; /* Latin glyphs */
}
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
src: local('Awesome Font'),
url('/fonts/awesome-jp.woff2') format('woff2'),
url('/fonts/awesome-jp.woff') format('woff'),
url('/fonts/awesome-jp.ttf') format('truetype'),
url('/fonts/awesome-jp.eot') format('embedded-opentype');
unicode-range: U+3000-9FFF, U+ff??; /* Japanese glyphs */
}
local()
directive allows you to reference, load, and use locally installed fonts. The url()
directive allows you to load external fonts, and are allowed to contain an optional format()
hint indicating the format of the font referenced by the provided URL.There is a catch however which is not all browsers currently support unicode-range. Fortunately most of the major browsers support it, you will need to have a fallback option.
Now if you’re asking how I can determine which subsets I need, the answer is:
@font-face
rules.You can generate the subsets using an open source tool called pyftsubset tool. In addition to that some font services allow manual subsetting via custom query parameters.
There are some other opportunities you can leverage apart from subsetting. Let’s say you just need a Google font to show your page title. You can specify which characters to download from that font only using a &text=
syntax:
<link
href="//fonts.googleapis.com/css?family=Roboto&text=log"
rel="stylesheet"
/>
l
, o
, and g
will be shown on Roboto.There are four major formats used on the web:
There isn’t one format that works in all of the browsers, hence the need to deliver multiple formats to provide a consistent experience. From Google developer’s website:
If majority of your users use modern web browsers you can get away with specifying just two formats:
@font-face {
font-family: 'Roboto';
src: local('Roboto'), local('Roboto'),
url(fonts/Roboto.woff2) format('woff2'), url(fonts/Roboto.woff)
format('woff');
}
Some users might already have the fonts installed on their system, so why they should be forced to download the fonts again. You can prevent this by making sure you give precedence to local()
in the src
attribute of font face rule.
In the above sample note how the src: local
is used before the url
.
By default the fonts are lazy loaded, which means the network request is delayed until the render tree is fully constructed, which in turn results in delayed text rendering.
There are three hooks you would need to implement a custom font loading strategy:
<link rel=preload>
font-display
propertyIf there is a high chance that the font is used in the page, then you can load the font eagerly using the platform feature: <link rel=preload>
.
This will tell the browser that the font should be fetched early, but it won’t specify how to use it. You will need to specify the appropriate CSS @font-face
:
<link
rel="preload"
href="/fonts/Roboto.woff2"
as="font"
/>
@font-face {
font-family: 'Awesome Font';
font-style: normal;
font-weight: 400;
/* will be preloaded */
src: local('Awesome Font'),
url('/fonts/awesome-l.woff2') format('woff2'),
url('/fonts/awesome-l.woff') format('woff'),
url('/fonts/awesome-l.ttf') format('truetype'),
url('/fonts/awesome-l.eot') format('embedded-opentype');
unicode-range: U+000-5FF; /* Latin glyphs */
}
For more info on the other solutions refer to this great post.
In short these are the points you have to consider when optimising web fonts:
local()
in your src
list.<link rel="preload">
, font-display
, or the Font Loading API.Hope this helps you move one more step in the right direction to improve your web application’s performance.