
Fixing render-blocking fonts
Learn how to fix render-blocking fonts and improve your website's page load speed with simple and effective techniques.
Render-blocking
fonts refer to fonts that prevent a web page from rendering or displaying its content until the font has been loaded. This can cause a delay in the page loading, resulting in a slower user experience.
When a web page is loaded, the browser reads the HTML and CSS files to determine the layout and styling of the page. If a font is specified in the CSS, the browser will typically wait for the font to be loaded before rendering the page. This is known as a render-blocking
font because it blocks the rendering of the page until the font is available.
Render-blocking
fonts can be a problem because they can cause a delay in the page loading, especially if the font is large or takes a long time to load.
To avoid render-blocking
fonts, let’s explore techniques to fix the issue.
Techniques that can be used to avoid render-blocking fonts
To avoid render-blocking fonts, the following techniques can be used:
- Using system fonts or fonts that are already loaded on the user’s device.
- Using CSS font loading APIs that allow the page to render before the font is loaded.
- Specifying a fallback font that can be used until the main font is loaded.
- Load fonts asynchronously using a technique called
font loading with a media query hack
.
Using system fonts or fonts that are already loaded on the user’s device
Using system fonts or fonts that are already loaded on the user’s device is a technique that helps improve the performance of your web page by reducing the need to load additional fonts.
System fonts are fonts that are already installed on the user’s device, such as their computer or mobile phone. These fonts are typically provided by the operating system or device manufacturer.
We recommend the following font family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
. This font family ensures cross-platform compatibility, readability and legibility, fallback options (ensuring that if the preferred fonts are unavailable, the text will still display in a legible manner), and a modern aesthetic.
Using CSS font loading APIs that allow the page to render before the font is loaded
Using CSS font loading APIs is a technique that allows a web page to render before the font is loaded. This approach uses JavaScript to load fonts asynchronously, which means that the page can render its content without waiting for the font to be loaded.
The FontFace API enables fonts to be loaded asynchronously, which can improve page performance by allowing the page to render before all fonts are fully loaded. This helps prevent the Flash of Unstyled Text
(FOUC) that occurs when a fallback font is displayed before the desired font is ready. You can create a new FontFace
object by specifying the font family name and the URL of the font file. Additional options, such as weight and style, can also be defined.
You can load a font like this:
const loadCustomFonts = async () => {
if (typeof document.fonts === "undefined") {
return;
}
const fonts = [
new FontFace("Inter", "url(assets/fonts/Inter-Regular.woff2)", {
style: "normal",
weight: "400",
}),
new FontFace("Inter", "url(assets/fonts/Inter-Medium.woff2)", {
style: "normal",
weight: "500",
}),
new FontFace("Inter", "url(assets/fonts/Inter-SemiBold.woff2)", {
style: "normal",
weight: "600",
})
];
const fontsToLoad = fonts.map((font) => {
document.fonts.add(font);
return font.load(font);
});
try {
await Promise.all(fontsToLoad);
} catch (err) {
console.error(`Unable to load a custom font ${fonts}`, err);
}
};
loadCustomFonts();
Specifying a fallback font that can be used until the main font is loaded
Specifying a fallback font is a technique that allows you to define a temporary font that can be used until the main font is loaded. This can help improve the user experience by providing a readable font while the main font is loading.
To specify a fallback font, you can use the font-family
property in your CSS and list multiple font families, separated by commas. The browser will try to use the first font family listed, and if it’s not available, it will fall back to the next font family, and so on.
font-family: "My Custom Font", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
This font family is often referred to as the “system font stack” because it uses the system font on each platform:
-apple-system
is the system font on macOS and iOS.BlinkMacSystemFont
is the system font on Chrome OS and some Linux distributions.Segoe UI
is the system font on Windows.Roboto
is the system font on Android.Helvetica Neue
is a fallback font on macOS and iOS if-apple-system
is not available.Arial
is a generic sans-serif font that will be used if none of the above fonts are available.sans-serif
is a generic font family that will be used if none of the above fonts are available.
Load fonts asynchronously using a technique called font loading with a media query hack
When a font is loaded using a traditional link
tag, the browser will wait for the font to be loaded before rendering the page. This can cause a delay in the page loading, especially if the font is large or the network connection is slow.
The font loading with a media query hack
technique is used to load fonts in a way that bypasses the browser’s default behavior of blocking font loading until the page has finished loading. It involves using a media query to initially load the font stylesheet only for print
media and then removing the media query once the font is loaded, allowing the font to be applied to the page.
Essentially, the link
tag has a media
attribute set to print
, which tells the browser to only load the font when the page is being printed, and at the same time, the browser sets the low loading priority.
The onload
event is triggered when the font has finished loading, at which point the JavaScript code inside the onload
attribute is executed. To prevent infinite loops, the onload
attribute is then set to null
. This event is also used to remove the media
attribute once the font has loaded, allowing it to be used on the page immediately without blocking the initial page load, even if it was initially loaded with a media query that would have otherwise prevented its use.
This technique is often referred to as a hack
because it uses a media
query in a non-standard way to achieve asynchronous font loading. However, it is a widely used and effective technique for improving page load times and user experience.
<link type="text/css" rel="stylesheet" media="print" href="https://fonts.googleapis.com/css2?family=Oxygen:wght@300;400;700&family=Work+Sans:wght@600;700&display=swap" onload="this.onload=null;window.requestAnimationFrame(()=>{this.removeAttribute('media')});">
<link type="text/css" rel="stylesheet" media="print" href="/css/font-awesome.css" onload="this.onload=null;window.requestAnimationFrame(()=>{this.removeAttribute('media')});">
The requestAnimationFrame
schedules the callback during the next browser repaint cycle, ensuring optimal timing for DOM modifications. This aligns perfectly with the browser’s rendering pipeline and provides better performance guarantees compared to setTimeout
.
Here is an example written in C# to use in an ASP.NET MVC application to include a CSS stylesheet in a Razor view:
@Html.Raw(
string.Format("<link type=\"text/css\" rel=\"stylesheet\" href=\"/styles/fonts.css?v={0}\" media=\"print\" onload=\"this.onload=null;window.requestAnimationFrame(()=>{{this.removeAttribute('media')}});\">",
System.IO.File.GetLastWriteTime(Server.MapPath("~/styles/fonts.css")).Ticks)
)
Note that System.IO.File.GetLastWriteTime(Server.MapPath("~/styles/fonts.css")).Ticks
gets the last write time of the fonts.css
file in ticks (a measure of time in 100-nanosecond intervals) and uses it as a query string parameter in the link
tag’s href
attribute. This is a common technique to bust the browser’s cache when the file changes.
Results and testing pages
You can use the following test pages, based on font loading with a media query hack
, and see how it works in your browser:
Comments