On this page
Virtual keyboard with virtual monitor that presents the code. Image by Gerd Altmann from Pixabay.

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:

CSS FontFace API usage example
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 with custom and fallback fonts
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.

Example of loading custom fonts with a media query hack
<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:

Example of loading custom fonts with a media query hack written in C#
@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:

Related posts

Comments

Leave a Reply

Search in sitelint.com

Is your site slow?

Discover performance bottlenecks to provide a better customer experience and meet your company’s revenue targets.

Real-user monitoring for Accessibility, Performance, Security, SEO & Errors (SiteLint)