Is it possible to preload or otherwise cache @font-face fonts, most likely with javascript, before the page loads so you don't get that ugly jump when the page finally does load?
Is it possible to preload or otherwise cache @font-face fonts, most likely with javascript, before the page loads so you don't get that ugly jump when the page finally does load?
Since 2017 you have preload
MDN: The preload value of the element's rel attribute allows you to write declarative fetch requests in your HTML , specifying resources that your pages will need very soon after loading, which you therefore want to start preloading early in the lifecycle of a page load, before the browser's main rendering machinery kicks in. This ensures that they are made available earlier and are less likely to block the page's first render, leading to performance improvements.
<link rel="preload" href="/fonts/myfont.eot" as="font" crossorigin="anonymous" />
<link rel="preload" href="/fonts/mywofffont.woff2" as="font" type="font/woff2" crossorigin>
Always check browser compatibility.
It is most useful for font preloading (not waiting for the browser to find it in some CSS). You can also preload some logos, icons and scripts.
Your head should include the preload rel as follows:
<head>
...
<link rel="preload" as="font" href="/somefolder/font-one.woff2">
<link rel="preload" as="font" href="/somefolder/font-two.woff2">
</head>
This way woff2 will be preloaded by browsers that support preload, and all the fallback formats will load as they normally do.
And your css font face should look similar to to this
@font-face {
font-family: FontOne;
src: url(../somefolder/font-one.eot);
src: url(../somefolder/font-one.eot?#iefix) format('embedded-opentype'),
url(../somefolder/font-one.woff2) format('woff2'), //Will be preloaded
url(../somefolder/font-one.woff) format('woff'),
url(../somefolder/font-one.ttf) format('truetype'),
url(../somefolder/font-one.svg#svgFontName) format('svg');
}
@font-face {
font-family: FontTwo;
src: url(../somefolder/font-two.eot);
src: url(../somefolder/font-two.eot?#iefix) format('embedded-opentype'),
url(../somefolder/font-two.woff2) format('woff2'), //Will be preloaded
url(../somefolder/font-two.woff) format('woff'),
url(../somefolder/font-two.ttf) format('truetype'),
url(../somefolder/font-two.svg#svgFontName) format('svg');
}
A first step, for sure, is pre-loading the font in HTML:
<link rel="preload" href="pacifico.woff2" as="font" crossorigin="anonymous">
Please, note that fonts are always pre-loaded with cross-origin resource sharing (CORS) enabled, even though the font resides on the same server:
When preloading resources that are fetched with CORS enabled (e.g. fetch(), XMLHttpRequest or fonts), special care needs to be taken to setting the crossorigin attribute on your element. The attribute needs to be set to match the resource's CORS and credentials mode, even when the fetch is not cross-origin.
Hence, the crossorigin="anonymous" attribute is absolutely necessary.
The same cannot be said about the optional type="MIME-type" attribute. There is much discordance between browsers and institutions about what MIME-type fonts should be. If the wrong type is stated for a certain browser, the font file will not be pre-loaded. Therefore, it is better to refrain from using the type="MIME-type" HTML attribute all together.
Then, there is what the cool kids call FOIT; the flash of invisible text.
In modern browsers, this FOIT can easily be avoided by adding the font-display: swap; property to the @font-face CSS declaration.
@font-face {
font-family: 'Pacifico';
font-style: normal;
font-weight: 400;
src: local('Pacifico Regular'), local('Pacifico-Regular'), url(pacifico.woff2) format('woff2');
font-display: swap;
}
As I found the best way is doing is preloading a stylesheet that contains the font face, and then let browser to load it automatically. I used the font-face in other locations (in the html page), but then I could observe the font changing effect briefly.
<link href="fonts.css?family=Open+Sans" rel="preload stylesheet" as="style">
then in the font.css file, specify as following.
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'),
url('open-sans-v16-latin-regular.woff2') format('woff2'); /* Super Modern Browsers */
}
You can't assign a name to fonts when it's preloaded through link tag (correct me if I was wrong I couldn't find a way yet), and thus you have to use font-face to assign the name to the font. Even though it's possible to load a font through link tag, it's not recommended as you can't assign a name to the font with it. Without a name as with font-face, you won't be able to use it anywhere in the web page. According to gtmetrix, style sheet loads at the beginning, then rest of the scripts/style by order, then the font before dom is loaded, and therefore you don't see font changing effect.
This should solve your problem.
To answer your initial question: yes you can. Only Gecko and WebKit browsers support it currently though.
You just need to add link tags in your head:
<link rel="prefetch" href="pathto/font">
<link rel="prerender" href="pathto/page">
Use the standard CSS Font Loading API.
Wait for (all) the fonts to load, and then show your content:
document.fonts.ready.then((fontFaceSet) => {
console.log(fontFaceSet.size, 'FontFaces loaded.');
document.getElementById('waitScreen').style.display = 'none';
});