{ "type": [ "h-entry" ], "properties": { "name": [ "A Comprehensive Guide to Font Loading Strategies" ], "published": [ "2020-02-01T20:14:26Z" ], "category": [ "font", "web", "performance" ], "bookmark-of": [ { "type": [ "h-cite" ], "properties": { "url": [ "https://www.zachleat.com/web/comprehensive-webfonts/" ], "name": [ "A Comprehensive Guide to Font Loading Strategies" ], "content": [ { "value": "
This guide is not intended for use with font icons, which have different loading priorities and use cases. Also, SVG is probably a better long term choice.
Updated July 27, 2017 with new information on font-display
.
Updated August 14, 2017 with a link to a glossary page.
font-display
preload
preload
If you run into a term that you don’t know, please consult the glossary of web font loading terms I’ve prepared. If a term is missing in the glossary, please let me know on Twitter @zachleat or in the comments.
If you’re looking for a specific approach, I’ve prepared some handy links that will take you to the section you need. Let’s say you want an approach that:
is the most well rounded approach that will be good enough for most use cases: FOUT with a Class.
is the easiest possible thing to implement: I’ve learned a lot about web fonts and at time of writing this article the current browser support is lacking for the easiest methods for effective/robust web font implementation. It is with that in mind that I will admit—if you’re looking for the easy way out already, you should consider not using web fonts. If you don’t know what web fonts are doing to improve your design, they may not be right for you. Don’t get me wrong, web fonts are great. But educate yourself on the benefit first. (In Defense of Web Fonts, The Value of a Web Font by Robin Rendle is a good start. If you have others, please leave a comment below!)
is the best performance-oriented approach: Use one of the Critical FOFT approaches. Personally, at time of writing my preference is Critical FOFT with Data URI but will shift toward Critical FOFT with preload
as browser support for preload
increases.
will work well with a large number of web fonts: If you’re web font obsessed (anything more than 4 or 5 web fonts or a total file size of more than 100KB) this one is kind of tricky. I’d first recommend trying to pare your web font usage down, but if that isn’t possible stick with a standard FOFT, or FOUT with Two Stage Render approach. Use separate FOFT approaches for each typeface (grouping of roman, bold, italic, et cetera).
will work with my existing cloud/web font hosting solution: FOFT approaches generally require self hosting, so stick with the tried and true FOUT with a Class approach.
Throw a naked @font-face block on your page and hope for the best. This is the default approach recommended by Google Fonts.
@font-face
block with WOFF and WOFF2 formats (maybe even an OpenType format too, if you want better Android < 4.4 support—Compare WOFF with TTF/OTF on Can I Use).@font-face
comma separated src
attribute.Add a new font-display: swap
descriptor to your @font-face
block to opt-in to FOUT on browsers that support it. Optionally, font-display: fallback
or font-display: optional
can be used if you consider web fonts to be unnecessary to the design. At time of writing, this feature is not available in any stable web browsers. Update: on July 25, 2017 Chrome 60 was released on the Chrome stable release channel which includes support for font-display
.
font-display
: note browser support for this is very limited.font-display
Specification@font-face
block.font-display
is a CSS-only approach. It’ll help for repeat view optimizations though.font-display
property, related blog post can be read here.@font-face
blocks, but by itself it’s not sufficient. #Add to fetch your font sooner. Pairs nicely with an unceremonious
@font-face
block and feel free to also throw in the font-display
descriptor as well for bonus points.
preload
Keep in mind: The pros and cons for this approach are heavily dependent on the font loading strategy you pair it with, whether it be Unceremonious @font-face
or font-display
.
and you’re off.@font-face
block. Web fonts are requested higher up in the waterfall.type
attribute to specify the font format. At this point it’s still possible (although it looks unlikely) that a web browser will implement preload before WOFF2 for example, and without this attribute you could be looking at a wasted request. So, make sure you include type
.I won’t go into this approach too much because, well, it isn’t technically a font loading strategy. But I will say that it’s better than using web fonts incorrectly. You are missing out on many new typographic features and improvements in readability that a web font can give you, but it is your option to opt-out.
font-family
without @font-face
.There are typically two kinds of inlining covered by this method: in a blocking request or in a
element in the server rendered markup. Both alibaba.com (two web fonts embedded in a blocking CSS request) and medium.com (seven web fonts) use this approach.
@font-face
blocks: this approach only embeds one format type. Usually in the wild this has meant WOFF, so using this method forces you to choose between ubiquity (WOFF) and much narrower user agent support but smaller file sizes (WOFF2).Use a tool like loadCSS
to fetch a stylesheet with all of the fonts embedded as Data URIs. Often you’ll see this coupled with a localStorage method of storing the stylesheet on the user agent for repeat views.
Use the CSS Font Loading API with a polyfill to detect when a specific font has loaded and only apply that web font in your CSS after it has loaded successfully. Usually this means toggling a class on your element. Use with SASS or LESS mixins for easier maintenance.
@font-face
blocks)@font-face
blocks. That means when a new format comes out, you can just change your @font-face
as normal.loaded
class will likely trigger a FOIT.@font-face
usage, newer browsers only download web fonts that are actually used on your page. This is given to you for free. This is why the New York Times can get away with 100 different @font-face
blocks on their home page—the browser only downloads a fraction of those. With this approach, you must tell the browser which fonts to download independent of usage.This approach builds on the FOUT with a Class method and is useful when you’re loading multiple weights or styles of the same typeface, e.g. roman, bold, italic, bold italic, book, heavy, and others. We split those web fonts into two stages: the roman first, which will then also immediately render faux-bold and faux-italic content (using font synthesis) while the real web fonts for heavier weights and alternative styles are loading.
The only difference between this method and standard FOFT approach is that instead of the full roman web font in the first stage, we use a subset roman web font (usually only containing A-Z and optionally 0-9 and/or punctuation). The full roman web font is instead loaded in the second stage with the other weights and styles.
This variation of the Critical FOFT approach simply changes the mechanism through which we load the first stage. Instead of using our normal font loading JavaScript API to initiate a download, we simply embed the web font as a inline Data URI directly in the markup. As previously discussed, this will block initial render but since we’re only embedding a very small subset roman web font this is a small price to pay to mostly eliminate FOUT.
preload
#This variation of the Critical FOFT approach simply changes the mechanism through which we load the first stage. Instead of using our normal font loading JavaScript API to initiate a download, we use the new preload
web standard as described above in the preload
method. This should trigger the download sooner than previously possible.
preload
(includes sessionStorage trick for repeat view optimization)preload
can marginally delay initial render (note data for this comparison was gathered on a site that was using Critical CSS)This guide is not intended for use with font icons, which have different loading priorities and use cases. Also, SVG is probably a better long term choice.
Updated July 27, 2017 with new information on font-display
.
Updated August 14, 2017 with a link to a glossary page.
font-display
preload
preload
If you run into a term that you don’t know, please consult the glossary of web font loading terms I’ve prepared. If a term is missing in the glossary, please let me know on Twitter @zachleat or in the comments.
If you’re looking for a specific approach, I’ve prepared some handy links that will take you to the section you need. Let’s say you want an approach that:
is the most well rounded approach that will be good enough for most use cases: FOUT with a Class.
is the easiest possible thing to implement: I’ve learned a lot about web fonts and at time of writing this article the current browser support is lacking for the easiest methods for effective/robust web font implementation. It is with that in mind that I will admit—if you’re looking for the easy way out already, you should consider not using web fonts. If you don’t know what web fonts are doing to improve your design, they may not be right for you. Don’t get me wrong, web fonts are great. But educate yourself on the benefit first. (In Defense of Web Fonts, The Value of a Web Font by Robin Rendle is a good start. If you have others, please leave a comment below!)
is the best performance-oriented approach: Use one of the Critical FOFT approaches. Personally, at time of writing my preference is Critical FOFT with Data URI but will shift toward Critical FOFT with preload
as browser support for preload
increases.
will work well with a large number of web fonts: If you’re web font obsessed (anything more than 4 or 5 web fonts or a total file size of more than 100KB) this one is kind of tricky. I’d first recommend trying to pare your web font usage down, but if that isn’t possible stick with a standard FOFT, or FOUT with Two Stage Render approach. Use separate FOFT approaches for each typeface (grouping of roman, bold, italic, et cetera).
will work with my existing cloud/web font hosting solution: FOFT approaches generally require self hosting, so stick with the tried and true FOUT with a Class approach.
Throw a naked @font-face block on your page and hope for the best. This is the default approach recommended by Google Fonts.
@font-face
block with WOFF and WOFF2 formats (maybe even an OpenType format too, if you want better Android < 4.4 support—Compare WOFF with TTF/OTF on Can I Use).@font-face
comma separated src
attribute.Add a new font-display: swap
descriptor to your @font-face
block to opt-in to FOUT on browsers that support it. Optionally, font-display: fallback
or font-display: optional
can be used if you consider web fonts to be unnecessary to the design. At time of writing, this feature is not available in any stable web browsers. Update: on July 25, 2017 Chrome 60 was released on the Chrome stable release channel which includes support for font-display
.
font-display
: note browser support for this is very limited.font-display
Specification@font-face
block.font-display
is a CSS-only approach. It’ll help for repeat view optimizations though.font-display
property, related blog post can be read here.@font-face
blocks, but by itself it’s not sufficient. #Add <link rel=\"preload\" href=\"font.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>
to fetch your font sooner. Pairs nicely with an unceremonious @font-face
block and feel free to also throw in the font-display
descriptor as well for bonus points.
preload
Keep in mind: The pros and cons for this approach are heavily dependent on the font loading strategy you pair it with, whether it be Unceremonious @font-face
or font-display
.
<link>
and you’re off.@font-face
block. Web fonts are requested higher up in the waterfall.type
attribute to specify the font format. At this point it’s still possible (although it looks unlikely) that a web browser will implement preload before WOFF2 for example, and without this attribute you could be looking at a wasted request. So, make sure you include type
.I won’t go into this approach too much because, well, it isn’t technically a font loading strategy. But I will say that it’s better than using web fonts incorrectly. You are missing out on many new typographic features and improvements in readability that a web font can give you, but it is your option to opt-out.
font-family
without @font-face
.There are typically two kinds of inlining covered by this method: in a blocking <link rel=\"stylesheet\">
request or in a <style>
element in the server rendered markup. Both alibaba.com (two web fonts embedded in a blocking CSS request) and medium.com (seven web fonts) use this approach.
@font-face
blocks: this approach only embeds one format type. Usually in the wild this has meant WOFF, so using this method forces you to choose between ubiquity (WOFF) and much narrower user agent support but smaller file sizes (WOFF2).Use a tool like loadCSS
to fetch a stylesheet with all of the fonts embedded as Data URIs. Often you’ll see this coupled with a localStorage method of storing the stylesheet on the user agent for repeat views.
Use the CSS Font Loading API with a polyfill to detect when a specific font has loaded and only apply that web font in your CSS after it has loaded successfully. Usually this means toggling a class on your <html>
element. Use with SASS or LESS mixins for easier maintenance.
@font-face
blocks)@font-face
blocks. That means when a new format comes out, you can just change your @font-face
as normal.loaded
class will likely trigger a FOIT.@font-face
usage, newer browsers only download web fonts that are actually used on your page. This is given to you for free. This is why the New York Times can get away with 100 different @font-face
blocks on their home page—the browser only downloads a fraction of those. With this approach, you must tell the browser which fonts to download independent of usage.This approach builds on the FOUT with a Class method and is useful when you’re loading multiple weights or styles of the same typeface, e.g. roman, bold, italic, bold italic, book, heavy, and others. We split those web fonts into two stages: the roman first, which will then also immediately render faux-bold and faux-italic content (using font synthesis) while the real web fonts for heavier weights and alternative styles are loading.
The only difference between this method and standard FOFT approach is that instead of the full roman web font in the first stage, we use a subset roman web font (usually only containing A-Z and optionally 0-9 and/or punctuation). The full roman web font is instead loaded in the second stage with the other weights and styles.
This variation of the Critical FOFT approach simply changes the mechanism through which we load the first stage. Instead of using our normal font loading JavaScript API to initiate a download, we simply embed the web font as a inline Data URI directly in the markup. As previously discussed, this will block initial render but since we’re only embedding a very small subset roman web font this is a small price to pay to mostly eliminate FOUT.
preload
#This variation of the Critical FOFT approach simply changes the mechanism through which we load the first stage. Instead of using our normal font loading JavaScript API to initiate a download, we use the new preload
web standard as described above in the preload
method. This should trigger the download sooner than previously possible.
preload
(includes sessionStorage trick for repeat view optimization)preload
can marginally delay initial render (note data for this comparison was gathered on a site that was using Critical CSS)