Preloading fonts in Chrome with 'preload' link directive

Tom picture Tom · Mar 6, 2017 · Viewed 11.5k times · Source

The preload directive is not performing in Chrome as expected. Below is a full HTML page that may be opened in Chrome for results comparison. It should be applying all 5 fonts; instead, it only applies the first preloaded font, makes a faux italic for what should be the second, and simply substitutes the default serif for the remaining 3.

Additionally, in the developer's console, this message appears--after about 3 seconds--for each of the five fonts:

The resource [URL] was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it wasn't preloaded for nothing.

Strangely, it did apply the first font (Muli) to the h1 and h2 tags (although making a faux italic for the h2); you can click on the URLs in the error messages and a preview of the preloaded font will appear in the developer's console.

Any clue what's amiss here? (I've tested this on Chrome 56 on Windows 8.1 Pro.)

<!DOCTYPE html>
<html>
<head>
    <title>Preload Font Test</title>
    <link rel="preload" href="https://fonts.gstatic.com/s/muli/v10/zscZFkjVRGyfQ_Pw-5exXPesZW2xOQ-xsNqO47m55DA.woff2" as="font" type="font/woff2" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/muli/v10/YxNEAWILjDc466nftZdqXuvvDin1pK8aKteLpeZ5c0A.woff2" as="font" type="font/woff2" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2" as="font" type="font/woff2" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxv79_ZuUxCigM2DespTnFaw.woff2" as="font" type="font/woff2" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/lato/v13/tI4j516nok_GrVf4dhunkg.woff2" as="font" type="font/woff2" crossorigin>
    <style>
        h1 {font-family:'Muli';font-weight:400;font-style:normal;font-size:1.5em}
        h2 {font-family:'Muli';font-weight:400;font-style:italic;font-size:1.5em}
        h3 {font-family:'Open Sans';font-weight:700;font-style:normal;font-size:1.5em}
        h4 {font-family:'Open Sans';font-weight:700;font-style:italic;font-size:1.5em}
        h5 {font-family:'Lato';font-weight:900;font-style:normal;font-size:1.5em}
    </style>
</head>
<body>
    <h1>This should be in Muli regular 400 -- and it is!</h1>
    <h2>This should be in Muli Italic 400 -- but it's faux Muli Italic :(</h2>
    <h3>This should be in Open Sans Bold 700 -- but it's the default serif!</h3>
    <h4>This should be in Open Sans BoldItalic 700  -- but it's the default serif!</h4>
    <h5>This should be in Lato ExtraBold 900  -- but it's the default serif!</h5>
</body>
</html>

Answer

Tom picture Tom · Mar 8, 2017

I've found the solution to this. Sadly, the W3C spec on preload links doesn't make this clear, and there seems to be a lot of confusion about this where programmers have posted questions about it, especially as regards the developer's console error message (Google that by itself to see how many people are getting it and are perplexed by it; it's indicative of how misunderstood this very useful directive is).

You cannot use the preload link by itself to load fonts. It must be used in conjunction with @font-face. Specifically, the preload link must precede the @font-face directive, and @font-face must occur soon after the preload link, if not immediately. It would seem that in the <head> section, the preload link should come last in your links, and then @font-face should immediately follow, either in a linked style sheet or in a <style> section that follows.

Here is a corrected version of the original code:

<!DOCTYPE html>
<html>
<head>
    <title>Preload Font Test</title>
    <link rel="preload" href="https://fonts.gstatic.com/s/muli/v10/zscZFkjVRGyfQ_Pw-5exXPesZW2xOQ-xsNqO47m55DA.woff2" as="font" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/muli/v10/YxNEAWILjDc466nftZdqXuvvDin1pK8aKteLpeZ5c0A.woff2" as="font" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2" as="font" type="font/woff2" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxv79_ZuUxCigM2DespTnFaw.woff2" as="font" type="font/woff2" crossorigin>
    <link rel="preload" href="https://fonts.gstatic.com/s/lato/v13/lEjOv129Q3iN1tuqWOeRBgLUuEpTyoUstqEm5AMlJo4.woff2" as="font" type="font/woff2" crossorigin>
    <style>
        @font-face{font-family:'Muli';font-weight:400;font-style:normal;src:url('https://fonts.gstatic.com/s/muli/v10/BkuZCUxEYxRfSu-XBj9_CA.eot');src:url('https://fonts.gstatic.com/s/muli/v10/BkuZCUxEYxRfSu-XBj9_CA.eot?#iefix') format('embedded-opentype'),
local('Muli Regular'),
local('Muli-regular'),
url('https://fonts.gstatic.com/s/muli/v10/zscZFkjVRGyfQ_Pw-5exXPesZW2xOQ-xsNqO47m55DA.woff2') format('woff2'),
url('https://fonts.gstatic.com/s/muli/v10/minRpKQdEvXRRS8oAbAtWvesZW2xOQ-xsNqO47m55DA.woff') format('woff'),
url('https://fonts.gstatic.com/s/muli/v10/BfQP1MR3mJNaumtWa4Tizg.ttf') format('truetype'),
url('https://fonts.gstatic.com/l/font?kit=5laWPvb-IgmGJk9r92y1Hw&skey=2b55aa3f2f059b75&v=v10#Muli') format('svg');}

@font-face{font-family:'Muli';font-weight:400;font-style:italic;src:url('https://fonts.gstatic.com/s/muli/v10/vurWTAYiHMPVScIey50dUQ.eot');src:url('https://fonts.gstatic.com/s/muli/v10/vurWTAYiHMPVScIey50dUQ.eot?#iefix') format('embedded-opentype'),
local('Muli Italic'),
local('Muli-italic'),
url('https://fonts.gstatic.com/s/muli/v10/YxNEAWILjDc466nftZdqXuvvDin1pK8aKteLpeZ5c0A.woff2') format('woff2'),
url('https://fonts.gstatic.com/s/muli/v10/DSOyST5zmfghBgRIogdupevvDin1pK8aKteLpeZ5c0A.woff') format('woff'),
url('https://fonts.gstatic.com/s/muli/v10/AQQ1r0_czneVCtTD9ckSEA.ttf') format('truetype'),
url('https://fonts.gstatic.com/l/font?kit=Ok1ULmeTg1kfss3jIu3xZQ&skey=f22af9a5d2e9fc47&v=v10#Muli') format('svg');}

@font-face{font-family:'Open Sans';font-weight:700;font-style:normal;
src:url('https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzHZ2MAKAc2x4R1uOSeegc5U.eot');
src:url('https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzHZ2MAKAc2x4R1uOSeegc5U.eot?#iefix') format('embedded-opentype'),
local('Open Sans Bold'),
local('Open-Sans-700'),
url('https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2') format('woff2'),
url('https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzKRDOzjiPcYnFooOUGCOsRk.woff') format('woff'),
url('https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzInF5uFdDttMLvmWuJdhhgs.ttf') format('truetype'),
url('https://fonts.gstatic.com/l/font?kit=k3k702ZOKiLJc3WVjuplzFlIn5tFQcqMuf-jhyJP0ps&skey=cd9e1a36bb25a3c3&v=v13#OpenSans') format('svg');}

@font-face{font-family:'Open Sans';font-weight:700;font-style:italic;src:url('https://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxrFt29aCHKT7otDW9l62Aag.eot');src:url('https://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxrFt29aCHKT7otDW9l62Aag.eot?#iefix') format('embedded-opentype'),
local('Open Sans Bold Italic'),
local('Open-Sans-700italic'),
url('https://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxv79_ZuUxCigM2DespTnFaw.woff2') format('woff2'),
url('https://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxhbnBKKEOwRKgsHDreGcocg.woff') format('woff'),
url('https://fonts.gstatic.com/s/opensans/v13/PRmiXeptR36kaC0GEAetxp_TkvowlIOtbR7ePgFOpF4.ttf') format('truetype'),
url('https://fonts.gstatic.com/l/font?kit=PRmiXeptR36kaC0GEAetxntNmQEE9wZ6UZlmiISB1pg&skey=7e5bb13249e84143&v=v13#OpenSans') format('svg');}

@font-face{font-family:'Lato';font-weight:900;font-style:normal;src:url('https://fonts.gstatic.com/s/lato/v13/BjDVcwQGWPX2RAidnkd0Bw.eot');src:url('https://fonts.gstatic.com/s/lato/v13/BjDVcwQGWPX2RAidnkd0Bw.eot?#iefix') format('embedded-opentype'),
local('Lato Black'),
local('Lato-900'),
url('https://fonts.gstatic.com/s/lato/v13/lEjOv129Q3iN1tuqWOeRBgLUuEpTyoUstqEm5AMlJo4.woff2') format('woff2'),
url('https://fonts.gstatic.com/s/lato/v13/G2uphNnNqGFMHLRsO_72ngLUuEpTyoUstqEm5AMlJo4.woff') format('woff'),
url('https://fonts.gstatic.com/s/lato/v13/4cKlrioa77J2iqTqBgkRWg.ttf') format('truetype'),
url('https://fonts.gstatic.com/l/font?kit=UxBsysUD4pfKXRb0IKmcRQ&skey=d01acf708cb3b73b&v=v13#Lato') format('svg');}

        h1 {font-family:'Muli';font-weight:400;font-style:normal;font-size:1.5em}
        h2 {font-family:'Muli';font-weight:400;font-style:italic;font-size:1.5em}
        h3 {font-family:'Open Sans';font-weight:700;font-style:normal;font-size:1.5em}
        h4 {font-family:'Open Sans';font-weight:700;font-style:italic;font-size:1.5em}
        h5 {font-family:'Lato';font-weight:900;font-style:normal;font-size:1.5em}

    </style>
</head>
<body>
    <h1>This should be in Muli regular 400 -- and it is!</h1>
    <h2>This should be in Muli Italic 400 -- and it is!</h2>
    <h3>This should be in Open Sans Bold 700 -- and it is!</h3>
    <h4>This should be in Open Sans BoldItalic 700 -- and it is!</h4>
    <h5>This should be in Lato ExtraBold 900 -- and it is!</h5>
</body>
</html>

This works, and it does, in fact, collect your fonts as part of the initial navigation of the critical rendering path, which is the principal benefit. preload is currently only supported by Chrome and Opera, but other browsers will surely follow.