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.
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>