vahdet
vahdet

Reputation: 6729

Lighthouse: Ensure text remains visible during loading MaterialDesignIcons Webfonts

I want to improve Google Lighthouse score of a web application built using Vuetify.

To increase the performance score, I have been trying to get rid of the diagnostics:

Ensure text remains visible during webfont load

Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading. Learn more

URL: https://cdn.jsdelivr.net/npm/@mdi/font@latest/fonts/materialdesignicons-webfont.woff2?v=4.5.95 (cdn.jsdelivr.net)

This outcome was also for installing Roboto through https://fonts.googleapis.com , and it disappeared when I added display=swap to the links as follows:

<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link 
  rel="preload" 
  as="style" 
  href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap" 
  crossorigin>
<link 
  rel="stylesheet" 
  href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap" 
  crossorigin>

However, apparently, it does not make any difference to add display=swap to MaterialDesignIcons css file like:

<link 
  rel="preload"
  as="style"
  href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css?display=swap"
  crossorigin>
<link 
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css?display=swap"
  crossorigin>

Doing so, the diagnostics item does not vanish. How should I load materialdesignicons.min.css so that the text remains visible during webfont load?

Upvotes: 12

Views: 2684

Answers (2)

Jesper Ingels
Jesper Ingels

Reputation: 75

To answer your question more specific:

Working with the Google Fonts API

What's happening is that with the Roboto font you're loading a stylesheet first instead of directly loading a font file. This stylesheet than contains the actual url's to the font's themselves and starts loading them using @font-face. If you paste this url: https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap into your browser's address bar and go there you can see so for yourself.

When talking to the Google fonts API (fonts.googleapis.com) you can add additional parameters to instruct the API to return a different result. In this case the parameter display=swap adds the CSS property font-display: swap; to the @font-face declaration.

The Material Design Icons are not loaded through the Google Fonts API (in your example) and therefore you don't have the same parameters available that the Google Fonts API provides.

Solution

There's different ways of loading and displaying an icon in a browser. So if your goal is to improve your page's performance than you might want to look into this. But if you want to keep using Material Design Icons as a font then the best way to use this (IMHO) would be to self host it.

So just copy the contents of https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css into a css file and load this in your application. And then add the CSS property font-display: swap yourself in the @font-face declaration.

Upvotes: 0

Zach Jensz
Zach Jensz

Reputation: 4063

Loading in the SVG rather than loading as a font is the best solution as it:

  • Only sends the required icons to the client (tree-shaking) as James Coyle also mentions
  • Has potential to be loaded inline instantly with content OR like an image

To load as a font you're downloading all of the icons which is around 400KB (larger than any modern JS framework) and can slow users on poor connections down massively even if you only use 10 of the 100s of icons. And each time new icons are added you also have to download those.

Now I would think the reason that display=swap does not make any difference with the webfont is because of how display swap works:

display=swap gives the font face an extremely small block period and an infinite swap period.

Font block period: If the font face is not loaded, any element attempting to use it must render an invisible fallback font face. If the font face successfully loads during this period, it is used normally.

Font swap period: If the font face is not loaded, any element attempting to use it must render a fallback font face. If the font face successfully loads during this period, it is used normally.

Read more on MDN

So the block period waits for the font with an invisible font for the user, and the swap period waits for the font with a fallback font face.
However unlike swapping a fancy "a" letter with "a" in a font already on the system, there's no fallback for something like an icon of a user with a cog in the corner...
So essentially the swap period acts the same as the block period and therefore display=swap functions the same as not setting it at all (display=auto - most often similar to display=block)!

Upvotes: 0

Related Questions