Search code examples
javascripthtmlcssfontsstorage

Store and set user selected font using Web API or Chrome Extension API?


I am developing a text editor that the user can select their own font, either by getting from Google Fonts or picking their own file. Assuming I stored the selected file in localStorage or chrome.storage and can retrieve the file back (but not in URL form like https:// or chrome-extension://), is it possible to apply the font to certain elements?

// Could be a Blob or ArrayBuffer or anything binary
// The storage form is probably base-64
const fontFile = await getSelectedFontAsync();

// Now I do not know how to put @font-face here since it's CSS

// How to set the font of this element?
document.querySelector(".label").style.fontFamily = "?";

I know I can download the font again from Google Fonts but then it wouldn't work when user is offline and the font would be downloaded again and again. This also doesn't work if user pick their own custom font that's not on Google Fonts.

I could use the File System Access API but user would have to pick the file/folder again every time they use the app. Also if they pick from Google Fonts, the file has to be downloaded again.

How do I use the font file that user has submitted/my app has stored the binary file? I prefer a general Web API solution but if I have to use Chrome Extension API, it's fine.


Solution

  • So I realized there is FontFace API thanks to this question. Thankfully FontFace not only accept a URL but also an ArrayBuffer so fonts can be dynamically loaded using Javascript.

    (async() => {
      // fontContent can be any ArrayBuffer, in this example I simply get a file from Fetch API
      const fontContent = await fetch("https://fonts.gstatic.com/s/tangerine/v17/IurY6Y5j_oScZZow4VOxCZZM.woff2").then(r => r.arrayBuffer());
      
      const font = new FontFace("tangerine", fontContent);
      await font.load();
      
      document.fonts.add(font);
    
      const el = document.querySelector("p");
      el.style.fontFamily = "tangerine";
    })();
    <p>My Text Here</p>