Abhinav
Abhinav

Reputation: 8168

Dynamically Load fonts

I need around 150 fonts for my project. Loading all the fonts initially increases the page load time.

I tried googling but could not find an answer.

Scenario:

User will select a font option from <select> tag. and upon click, I have to retrieve the font dynamically and make sure the font is rendered by the browser and then use the font to avoid a Flash of Unstyled Text (FOUT)

Currently I am using AJAX to request that font file

      $.ajax({
      type: 'GET',
        url: "font-file-url",
        async:false,
        success: function(data) {
            $("style").prepend("@font-face {\n" +
            "\tfont-family: \""+fontValue+"\";\n" + 
            "\tsrc: local('☺'), url("font-file-url") format('opentype');\n" + 
            "}");
         }
      });

Problem

I dont know when exactly the font is being rendered by the browser, so I end up displaying FOUT

Upvotes: 16

Views: 24979

Answers (5)

Alexandr Petrov
Alexandr Petrov

Reputation: 26

Created function by comment above. This function returns a promise.

function loadFont(name, url, weight) {
  return new Promise((resolve, reject) => {
    const myFont = new FontFace(name, `url(${url})`);
    myFont.weight = weight;
    myFont
      .load()
      .then(() => {
        document.fonts.add(myFont);
        const el = document.createElement("DIV");
        el.style.fontFamily = name;
        resolve();
      })
      .catch(() => reject());
  });
}
loadFont('Ubuntu', 'https://fonts.cdnfonts.com/s/13098/Ubuntu-B.woff', 700).then(() => {
  alert('font loaded!');
});
<div style="font-family: 'Ubuntu'; font-weight: bold">
  Please check Network in devTools
</div>

Upvotes: 0

user9408899
user9408899

Reputation: 4540

You can use the native Font Loading API, a 3rd party package is no longer needed. Here is a working example:

document.getElementsByTagName('button')[0].onclick = async function() {

  const myFont = new FontFace('Pacifico', 'url(https://fonts.gstatic.com/s/pacifico/v21/FwZY7-Qmy14u9lezJ-6H6MmBp0u-.woff2)');
  await myFont.load();
  document.fonts.add(myFont);

  document.getElementsByTagName('h1')[0].style.fontFamily = "Pacifico";
}
<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
  <h1>Hello world!</h1>
  <button>Dynamically load font</button>
</body>

</html>

Upvotes: 17

CrazyTim
CrazyTim

Reputation: 7314

You can now use the Font Loading API to detect when all fonts have been loaded. This should work in most modern browsers.

// Wait until all fonts are loaded:
document.fonts.ready.then(() => init());

Upvotes: 2

Abhinav
Abhinav

Reputation: 8168

May be a bit late, but I accomplished it using Google's WebfontLoader Library. It did the job for me.

This is how I implemented:

Step 1: Include the JS file of the library

Step 2: The below code did the trick for me

WebFont.load({
google: {
  families: ['Droid Sans']
},
timeout:5000,
fontactive: function(familyName,fvd){ //This is called once font has been rendered in browser
    // Your business logic goes here

  },
});

You can also load custom fonts apart from google fonts. Library also provides various callback functions and other cool stuffs. You can check out the above link.

Upvotes: 13

H A&#223;d&#248;&#181;
H A&#223;d&#248;&#181;

Reputation: 3055

Unfortunately loading a font is not supported 100% by JavaScript. but there is a work about this to support it in future:

https://developer.mozilla.org/en-US/docs/Web/API/CSS_Font_Loading_API https://drafts.csswg.org/css-font-loading/

Upvotes: 2

Related Questions