[{"data":1,"prerenderedAt":1531},["ShallowReactive",2],{"blog-post:dynamic-font-loading":3},{"id":4,"title":5,"body":6,"date":1520,"description":1521,"draft":1522,"extension":1523,"lastModified":1524,"meta":1525,"navigation":188,"path":1526,"readingTime":1527,"seo":1528,"stem":1529,"__hash__":1530},"posts\u002Fblog\u002Fdynamic-font-loading.md","Dynamic font loading with FontFace",{"type":7,"value":8,"toc":1518},"minimark",[9,13,26,29,425,428,438,463,474,481,569,592,620,838,864,873,876,1468,1471,1482,1485,1515],[10,11,12],"p",{},"There are a few use-cases where you'd like to load a completely different font\nand apply it to your styles. By load I mean, download\u002Ffetch the font resource\nfile and use that font in your CSS or let's say you don't really know which font\nwould be used in the page ahead of time.",[10,14,15,16,20,21,25],{},"That's where ",[17,18,19],"strong",{},"CSS Font Loading API"," comes in to help. It includes ",[22,23,24],"code",{},"FontFace","\nclass that provides handy utilities to load dynamic fonts over network.",[10,27,28],{},"Let's consider this sample code below (I'm using Vue 3):",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-html shiki shiki-themes github-dark","\u003Ctemplate>\n  \u003Ch1 :style=\"`font-family: ${selectedFont ?? 'inherit'};`\">Hello World!\u003C\u002Fh1>\n  \u003Cselect v-model=\"selectedFont\">\n    \u003Coption\n      :key=\"font.fontName\"\n      v-for=\"font in fontsList\"\n      :value=\"font.fontName\"\n    >\n      {{ font.fontName }}\n    \u003C\u002Foption>\n  \u003C\u002Fselect>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n  import { ref } from \"vue\";\n  export default {\n    name: \"App\",\n    setup() {\n      let getFontsListFromAPI = () => {\n        \u002F\u002F TODO: get fonts list from API\n        return [\n          { fontName: \"Roboto\", resourcePath: \"..\" },\n          { fontName: \"Avenir\", resourcePath: \"..\" },\n        ];\n      };\n      let fontsList = getFontsListFromAPI();\n      let selectedFont = ref(null);\n      return { fontsList, selectedFont };\n    },\n  };\n\u003C\u002Fscript>\n\u003Cstyle>\n  \u002F**\u002F\n\u003C\u002Fstyle>\n","html","",[22,37,38,54,81,99,108,119,130,140,146,152,163,173,183,190,200,219,231,243,252,272,279,288,306,320,326,332,347,370,379,385,391,400,410,416],{"__ignoreMap":35},[39,40,43,47,51],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"s95oV","\u003C",[39,48,50],{"class":49},"s4JwU","template",[39,52,53],{"class":45},">\n",[39,55,57,60,63,67,70,74,77,79],{"class":41,"line":56},2,[39,58,59],{"class":45},"  \u003C",[39,61,62],{"class":49},"h1",[39,64,66],{"class":65},"svObZ"," :style",[39,68,69],{"class":45},"=",[39,71,73],{"class":72},"sU2Wk","\"`font-family: ${selectedFont ?? 'inherit'};`\"",[39,75,76],{"class":45},">Hello World!\u003C\u002F",[39,78,62],{"class":49},[39,80,53],{"class":45},[39,82,84,86,89,92,94,97],{"class":41,"line":83},3,[39,85,59],{"class":45},[39,87,88],{"class":49},"select",[39,90,91],{"class":65}," v-model",[39,93,69],{"class":45},[39,95,96],{"class":72},"\"selectedFont\"",[39,98,53],{"class":45},[39,100,102,105],{"class":41,"line":101},4,[39,103,104],{"class":45},"    \u003C",[39,106,107],{"class":49},"option\n",[39,109,111,114,116],{"class":41,"line":110},5,[39,112,113],{"class":65},"      :key",[39,115,69],{"class":45},[39,117,118],{"class":72},"\"font.fontName\"\n",[39,120,122,125,127],{"class":41,"line":121},6,[39,123,124],{"class":65},"      v-for",[39,126,69],{"class":45},[39,128,129],{"class":72},"\"font in fontsList\"\n",[39,131,133,136,138],{"class":41,"line":132},7,[39,134,135],{"class":65},"      :value",[39,137,69],{"class":45},[39,139,118],{"class":72},[39,141,143],{"class":41,"line":142},8,[39,144,145],{"class":45},"    >\n",[39,147,149],{"class":41,"line":148},9,[39,150,151],{"class":45},"      {{ font.fontName }}\n",[39,153,155,158,161],{"class":41,"line":154},10,[39,156,157],{"class":45},"    \u003C\u002F",[39,159,160],{"class":49},"option",[39,162,53],{"class":45},[39,164,166,169,171],{"class":41,"line":165},11,[39,167,168],{"class":45},"  \u003C\u002F",[39,170,88],{"class":49},[39,172,53],{"class":45},[39,174,176,179,181],{"class":41,"line":175},12,[39,177,178],{"class":45},"\u003C\u002F",[39,180,50],{"class":49},[39,182,53],{"class":45},[39,184,186],{"class":41,"line":185},13,[39,187,189],{"emptyLinePlaceholder":188},true,"\n",[39,191,193,195,198],{"class":41,"line":192},14,[39,194,46],{"class":45},[39,196,197],{"class":49},"script",[39,199,53],{"class":45},[39,201,203,207,210,213,216],{"class":41,"line":202},15,[39,204,206],{"class":205},"snl16","  import",[39,208,209],{"class":45}," { ref } ",[39,211,212],{"class":205},"from",[39,214,215],{"class":72}," \"vue\"",[39,217,218],{"class":45},";\n",[39,220,222,225,228],{"class":41,"line":221},16,[39,223,224],{"class":205},"  export",[39,226,227],{"class":205}," default",[39,229,230],{"class":45}," {\n",[39,232,234,237,240],{"class":41,"line":233},17,[39,235,236],{"class":45},"    name: ",[39,238,239],{"class":72},"\"App\"",[39,241,242],{"class":45},",\n",[39,244,246,249],{"class":41,"line":245},18,[39,247,248],{"class":65},"    setup",[39,250,251],{"class":45},"() {\n",[39,253,255,258,261,264,267,270],{"class":41,"line":254},19,[39,256,257],{"class":205},"      let",[39,259,260],{"class":65}," getFontsListFromAPI",[39,262,263],{"class":205}," =",[39,265,266],{"class":45}," () ",[39,268,269],{"class":205},"=>",[39,271,230],{"class":45},[39,273,275],{"class":41,"line":274},20,[39,276,278],{"class":277},"sAwPA","        \u002F\u002F TODO: get fonts list from API\n",[39,280,282,285],{"class":41,"line":281},21,[39,283,284],{"class":205},"        return",[39,286,287],{"class":45}," [\n",[39,289,291,294,297,300,303],{"class":41,"line":290},22,[39,292,293],{"class":45},"          { fontName: ",[39,295,296],{"class":72},"\"Roboto\"",[39,298,299],{"class":45},", resourcePath: ",[39,301,302],{"class":72},"\"..\"",[39,304,305],{"class":45}," },\n",[39,307,309,311,314,316,318],{"class":41,"line":308},23,[39,310,293],{"class":45},[39,312,313],{"class":72},"\"Avenir\"",[39,315,299],{"class":45},[39,317,302],{"class":72},[39,319,305],{"class":45},[39,321,323],{"class":41,"line":322},24,[39,324,325],{"class":45},"        ];\n",[39,327,329],{"class":41,"line":328},25,[39,330,331],{"class":45},"      };\n",[39,333,335,337,340,342,344],{"class":41,"line":334},26,[39,336,257],{"class":205},[39,338,339],{"class":45}," fontsList ",[39,341,69],{"class":205},[39,343,260],{"class":65},[39,345,346],{"class":45},"();\n",[39,348,350,352,355,357,360,363,367],{"class":41,"line":349},27,[39,351,257],{"class":205},[39,353,354],{"class":45}," selectedFont ",[39,356,69],{"class":205},[39,358,359],{"class":65}," ref",[39,361,362],{"class":45},"(",[39,364,366],{"class":365},"sDLfK","null",[39,368,369],{"class":45},");\n",[39,371,373,376],{"class":41,"line":372},28,[39,374,375],{"class":205},"      return",[39,377,378],{"class":45}," { fontsList, selectedFont };\n",[39,380,382],{"class":41,"line":381},29,[39,383,384],{"class":45},"    },\n",[39,386,388],{"class":41,"line":387},30,[39,389,390],{"class":45},"  };\n",[39,392,394,396,398],{"class":41,"line":393},31,[39,395,178],{"class":45},[39,397,197],{"class":49},[39,399,53],{"class":45},[39,401,403,405,408],{"class":41,"line":402},32,[39,404,46],{"class":45},[39,406,407],{"class":49},"style",[39,409,53],{"class":45},[39,411,413],{"class":41,"line":412},33,[39,414,415],{"class":277},"  \u002F**\u002F\n",[39,417,419,421,423],{"class":41,"line":418},34,[39,420,178],{"class":45},[39,422,407],{"class":49},[39,424,53],{"class":45},[10,426,427],{},"Output:",[10,429,430],{},[431,432],"img",{"alt":433,"dataZoomable":35,"height":434,"loading":435,"src":436,"width":437},"Example Font Loading",450,"lazy","\u002Fcontent\u002Ffont-preview.png",1240,[10,439,440,441,444,445,448,449,452,453,455,456,459,460,462],{},"Here we have a simple font selection dropdown which is ",[22,442,443],{},"v-model"," bound to a\n",[22,446,447],{},"ref"," with name ",[22,450,451],{},"selectedFont",". Based on the value of ",[22,454,451],{}," we set the\n",[22,457,458],{},"font-family"," style to our heading ",[22,461,62],{},".",[10,464,465,466,469,470,473],{},"The values of the dropdown are font names that are obtained from an API\nendpoint. Since the list of fonts and their resource paths are dynamic we can't\nreally use \u002F define CSS styles that can accommodate for different font names\nunless you use some hack with binding font names and resource paths to the\nheading tags and using ",[22,467,468],{},"attr(..)"," ",[22,471,472],{},"url(..)"," etc.",[10,475,476,477,480],{},"Now to load dynamic fonts we can create a helper method in our ",[22,478,479],{},"setup"," as\nfollows:",[30,482,486],{"className":483,"code":484,"language":485,"meta":35,"style":35},"language-js shiki shiki-themes github-dark","\u002F\u002F inside setup()\n\u002F\u002F ..\nlet loadFont = async (fontName, url) => {\n  let fontFace = new FontFace(fontName, `url(${url})`);\n};\n\u002F\u002F ..\n","js",[22,487,488,493,498,531,560,565],{"__ignoreMap":35},[39,489,490],{"class":41,"line":42},[39,491,492],{"class":277},"\u002F\u002F inside setup()\n",[39,494,495],{"class":41,"line":56},[39,496,497],{"class":277},"\u002F\u002F ..\n",[39,499,500,503,506,508,511,514,518,521,524,527,529],{"class":41,"line":83},[39,501,502],{"class":205},"let",[39,504,505],{"class":65}," loadFont",[39,507,263],{"class":205},[39,509,510],{"class":205}," async",[39,512,513],{"class":45}," (",[39,515,517],{"class":516},"s9osk","fontName",[39,519,520],{"class":45},", ",[39,522,523],{"class":516},"url",[39,525,526],{"class":45},") ",[39,528,269],{"class":205},[39,530,230],{"class":45},[39,532,533,536,539,541,544,547,550,553,555,558],{"class":41,"line":101},[39,534,535],{"class":205},"  let",[39,537,538],{"class":45}," fontFace ",[39,540,69],{"class":205},[39,542,543],{"class":205}," new",[39,545,546],{"class":65}," FontFace",[39,548,549],{"class":45},"(fontName, ",[39,551,552],{"class":72},"`url(${",[39,554,523],{"class":45},[39,556,557],{"class":72},"})`",[39,559,369],{"class":45},[39,561,562],{"class":41,"line":110},[39,563,564],{"class":45},"};\n",[39,566,567],{"class":41,"line":121},[39,568,497],{"class":277},[10,570,571,572,574,575,578,579,581,582,589,590,462],{},"Here we create a new instance of ",[22,573,24],{}," with ",[576,577,517],"em",{}," and ",[576,580,523],{}," as two\nparameters. The second parameter of the constructor must be either a URL or a\nbinary font data. We can then use Vue's\n",[583,584,588],"a",{"href":585,"rel":586},"https:\u002F\u002Fv3.vuejs.org\u002Fapi\u002Fcomputed-watch-api.html#watch",[587],"nofollow","watch"," method to track\nchanges of the dropdown which is v-modeled to ",[22,591,451],{},[10,593,594,595,597,598,601,602,605,606,609,610,612,613,616,617,462],{},"The ",[22,596,24],{}," class provides a ",[22,599,600],{},"load()"," method which actually loads the font\nand returns a ",[22,603,604],{},"Promise",". Make sure to wrap it with the ",[22,607,608],{},"try\u002Fcatch"," block. The\nvalue of ",[22,611,451],{}," is the font name i.e String. So we'll have to get the\noriginal font object from our fonts list and call ",[22,614,615],{},"loadFont(..)"," using the font\nobject ",[576,618,619],{},"(There a better ways of doing this)",[30,621,623],{"className":483,"code":622,"language":485,"meta":35,"style":35},"\u002F\u002F import { ref, watch } from \"vue\";\n\u002F\u002F inside setup()\n\u002F\u002F...\nlet loadFont = async (fontName, url) => {\n  try {\n    let fontFace = new FontFace(fontName, `url(${url})`);\n    console.log(`Loading font: ${fontName}...`);\n    await fontFace.load();\n    document.fonts.add(fontFace);\n  } catch (e) {\n    console.error(e);\n  }\n};\n\nwatch(selectedFont, (fontName) => {\n  let font = fontsList.find((f) => f.fontName === fontName);\n  loadFont(font.fontName, font.resourcePath);\n});\n\u002F\u002F ...\n",[22,624,625,630,634,639,663,670,693,713,726,737,748,758,763,767,771,786,820,828,833],{"__ignoreMap":35},[39,626,627],{"class":41,"line":42},[39,628,629],{"class":277},"\u002F\u002F import { ref, watch } from \"vue\";\n",[39,631,632],{"class":41,"line":56},[39,633,492],{"class":277},[39,635,636],{"class":41,"line":83},[39,637,638],{"class":277},"\u002F\u002F...\n",[39,640,641,643,645,647,649,651,653,655,657,659,661],{"class":41,"line":101},[39,642,502],{"class":205},[39,644,505],{"class":65},[39,646,263],{"class":205},[39,648,510],{"class":205},[39,650,513],{"class":45},[39,652,517],{"class":516},[39,654,520],{"class":45},[39,656,523],{"class":516},[39,658,526],{"class":45},[39,660,269],{"class":205},[39,662,230],{"class":45},[39,664,665,668],{"class":41,"line":110},[39,666,667],{"class":205},"  try",[39,669,230],{"class":45},[39,671,672,675,677,679,681,683,685,687,689,691],{"class":41,"line":121},[39,673,674],{"class":205},"    let",[39,676,538],{"class":45},[39,678,69],{"class":205},[39,680,543],{"class":205},[39,682,546],{"class":65},[39,684,549],{"class":45},[39,686,552],{"class":72},[39,688,523],{"class":45},[39,690,557],{"class":72},[39,692,369],{"class":45},[39,694,695,698,701,703,706,708,711],{"class":41,"line":132},[39,696,697],{"class":45},"    console.",[39,699,700],{"class":65},"log",[39,702,362],{"class":45},[39,704,705],{"class":72},"`Loading font: ${",[39,707,517],{"class":45},[39,709,710],{"class":72},"}...`",[39,712,369],{"class":45},[39,714,715,718,721,724],{"class":41,"line":142},[39,716,717],{"class":205},"    await",[39,719,720],{"class":45}," fontFace.",[39,722,723],{"class":65},"load",[39,725,346],{"class":45},[39,727,728,731,734],{"class":41,"line":148},[39,729,730],{"class":45},"    document.fonts.",[39,732,733],{"class":65},"add",[39,735,736],{"class":45},"(fontFace);\n",[39,738,739,742,745],{"class":41,"line":154},[39,740,741],{"class":45},"  } ",[39,743,744],{"class":205},"catch",[39,746,747],{"class":45}," (e) {\n",[39,749,750,752,755],{"class":41,"line":165},[39,751,697],{"class":45},[39,753,754],{"class":65},"error",[39,756,757],{"class":45},"(e);\n",[39,759,760],{"class":41,"line":175},[39,761,762],{"class":45},"  }\n",[39,764,765],{"class":41,"line":185},[39,766,564],{"class":45},[39,768,769],{"class":41,"line":192},[39,770,189],{"emptyLinePlaceholder":188},[39,772,773,775,778,780,782,784],{"class":41,"line":202},[39,774,588],{"class":65},[39,776,777],{"class":45},"(selectedFont, (",[39,779,517],{"class":516},[39,781,526],{"class":45},[39,783,269],{"class":205},[39,785,230],{"class":45},[39,787,788,790,793,795,798,801,804,807,809,811,814,817],{"class":41,"line":221},[39,789,535],{"class":205},[39,791,792],{"class":45}," font ",[39,794,69],{"class":205},[39,796,797],{"class":45}," fontsList.",[39,799,800],{"class":65},"find",[39,802,803],{"class":45},"((",[39,805,806],{"class":516},"f",[39,808,526],{"class":45},[39,810,269],{"class":205},[39,812,813],{"class":45}," f.fontName ",[39,815,816],{"class":205},"===",[39,818,819],{"class":45}," fontName);\n",[39,821,822,825],{"class":41,"line":233},[39,823,824],{"class":65},"  loadFont",[39,826,827],{"class":45},"(font.fontName, font.resourcePath);\n",[39,829,830],{"class":41,"line":245},[39,831,832],{"class":45},"});\n",[39,834,835],{"class":41,"line":254},[39,836,837],{"class":277},"\u002F\u002F ...\n",[10,839,840,841,843,844,846,847,850,851,854,855,860,861,863],{},"When a value in the dropdown is selected the ",[22,842,451],{}," ref gets updated\nwhich is tracked by our ",[22,845,588],{}," that intern calls ",[22,848,849],{},"loadFont",". On calling\n",[22,852,853],{},"fontFace.load()",", browser will fetch the font resource and add it to the\n",[583,856,859],{"href":857,"rel":858},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FDocument\u002Ffonts",[587],"Document Fonts","\nlist and since our heading tag (h1) has ",[22,862,451],{}," named font family, it is\nrendered accordingly.",[10,865,594,866,868,869,872],{},[22,867,24],{}," constructor takes ",[576,870,871],{},"descriptors"," as an optional third argument\nwhere you can specify things like style, variant, weight of the font face.",[10,874,875],{},"Final Code:",[30,877,881],{"className":878,"code":879,"language":880,"meta":35,"style":35},"language-vue shiki shiki-themes github-dark","\u003Ctemplate>\n  \u003Ch1 :style=\"`font-family: ${selectedFont ?? 'inherit'};`\">Hello World!\u003C\u002Fh1>\n  \u003Cselect v-model=\"selectedFont\">\n    \u003Coption\n      :key=\"font.fontName\"\n      v-for=\"font in fontsList\"\n      :value=\"font.fontName\"\n    >\n      {{ font.fontName }}\n    \u003C\u002Foption>\n  \u003C\u002Fselect>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\nimport { ref, watch } from \"vue\";\nexport default {\n  name: \"App\",\n  setup() {\n    let getFontsListFromAPI = () => {\n      \u002F\u002F TODO: get fonts list from API\n      return [\n        {\n          fontName: \"Roboto\",\n          resourcePath: \"..\",\n        },\n        {\n          fontName: \"Poppins\",\n          resourcePath: \"..\",\n        },\n      ];\n    };\n\n    let fontsList = getFontsListFromAPI();\n    let selectedFont = ref(null);\n\n    let loadFont = async (fontName, url) => {\n      let fontFace = new FontFace(fontName, `url(${url})`);\n      console.log(`Loading font: ${fontName}...`);\n      await fontFace.load();\n      document.fonts.add(fontFace);\n    };\n\n    watch(selectedFont, (fontName) => {\n      let font = fontsList.find((f) => f.fontName === fontName);\n      loadFont(font.fontName, font.resourcePath);\n    });\n\n    return { fontsList, selectedFont };\n  },\n};\n\u003C\u002Fscript>\n\u003Cstyle>\n#app {\n  font-family: \"Times New Roman\", sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-align: center;\n  color: #2c3e50;\n  margin-top: 60px;\n}\n\u003C\u002Fstyle>\n","vue",[22,882,883,891,909,923,929,937,945,953,957,961,969,977,985,989,997,1011,1020,1029,1036,1050,1055,1061,1066,1075,1084,1089,1093,1102,1110,1114,1119,1124,1128,1140,1156,1161,1186,1209,1227,1239,1249,1254,1259,1275,1302,1310,1316,1321,1329,1335,1340,1349,1358,1366,1385,1398,1411,1424,1437,1453,1459],{"__ignoreMap":35},[39,884,885,887,889],{"class":41,"line":42},[39,886,46],{"class":45},[39,888,50],{"class":49},[39,890,53],{"class":45},[39,892,893,895,897,899,901,903,905,907],{"class":41,"line":56},[39,894,59],{"class":45},[39,896,62],{"class":49},[39,898,66],{"class":65},[39,900,69],{"class":45},[39,902,73],{"class":72},[39,904,76],{"class":45},[39,906,62],{"class":49},[39,908,53],{"class":45},[39,910,911,913,915,917,919,921],{"class":41,"line":83},[39,912,59],{"class":45},[39,914,88],{"class":49},[39,916,91],{"class":65},[39,918,69],{"class":45},[39,920,96],{"class":72},[39,922,53],{"class":45},[39,924,925,927],{"class":41,"line":101},[39,926,104],{"class":45},[39,928,107],{"class":49},[39,930,931,933,935],{"class":41,"line":110},[39,932,113],{"class":65},[39,934,69],{"class":45},[39,936,118],{"class":72},[39,938,939,941,943],{"class":41,"line":121},[39,940,124],{"class":65},[39,942,69],{"class":45},[39,944,129],{"class":72},[39,946,947,949,951],{"class":41,"line":132},[39,948,135],{"class":65},[39,950,69],{"class":45},[39,952,118],{"class":72},[39,954,955],{"class":41,"line":142},[39,956,145],{"class":45},[39,958,959],{"class":41,"line":148},[39,960,151],{"class":45},[39,962,963,965,967],{"class":41,"line":154},[39,964,157],{"class":45},[39,966,160],{"class":49},[39,968,53],{"class":45},[39,970,971,973,975],{"class":41,"line":165},[39,972,168],{"class":45},[39,974,88],{"class":49},[39,976,53],{"class":45},[39,978,979,981,983],{"class":41,"line":175},[39,980,178],{"class":45},[39,982,50],{"class":49},[39,984,53],{"class":45},[39,986,987],{"class":41,"line":185},[39,988,189],{"emptyLinePlaceholder":188},[39,990,991,993,995],{"class":41,"line":192},[39,992,46],{"class":45},[39,994,197],{"class":49},[39,996,53],{"class":45},[39,998,999,1002,1005,1007,1009],{"class":41,"line":202},[39,1000,1001],{"class":205},"import",[39,1003,1004],{"class":45}," { ref, watch } ",[39,1006,212],{"class":205},[39,1008,215],{"class":72},[39,1010,218],{"class":45},[39,1012,1013,1016,1018],{"class":41,"line":221},[39,1014,1015],{"class":205},"export",[39,1017,227],{"class":205},[39,1019,230],{"class":45},[39,1021,1022,1025,1027],{"class":41,"line":233},[39,1023,1024],{"class":45},"  name: ",[39,1026,239],{"class":72},[39,1028,242],{"class":45},[39,1030,1031,1034],{"class":41,"line":245},[39,1032,1033],{"class":65},"  setup",[39,1035,251],{"class":45},[39,1037,1038,1040,1042,1044,1046,1048],{"class":41,"line":254},[39,1039,674],{"class":205},[39,1041,260],{"class":65},[39,1043,263],{"class":205},[39,1045,266],{"class":45},[39,1047,269],{"class":205},[39,1049,230],{"class":45},[39,1051,1052],{"class":41,"line":274},[39,1053,1054],{"class":277},"      \u002F\u002F TODO: get fonts list from API\n",[39,1056,1057,1059],{"class":41,"line":281},[39,1058,375],{"class":205},[39,1060,287],{"class":45},[39,1062,1063],{"class":41,"line":290},[39,1064,1065],{"class":45},"        {\n",[39,1067,1068,1071,1073],{"class":41,"line":308},[39,1069,1070],{"class":45},"          fontName: ",[39,1072,296],{"class":72},[39,1074,242],{"class":45},[39,1076,1077,1080,1082],{"class":41,"line":322},[39,1078,1079],{"class":45},"          resourcePath: ",[39,1081,302],{"class":72},[39,1083,242],{"class":45},[39,1085,1086],{"class":41,"line":328},[39,1087,1088],{"class":45},"        },\n",[39,1090,1091],{"class":41,"line":334},[39,1092,1065],{"class":45},[39,1094,1095,1097,1100],{"class":41,"line":349},[39,1096,1070],{"class":45},[39,1098,1099],{"class":72},"\"Poppins\"",[39,1101,242],{"class":45},[39,1103,1104,1106,1108],{"class":41,"line":372},[39,1105,1079],{"class":45},[39,1107,302],{"class":72},[39,1109,242],{"class":45},[39,1111,1112],{"class":41,"line":381},[39,1113,1088],{"class":45},[39,1115,1116],{"class":41,"line":387},[39,1117,1118],{"class":45},"      ];\n",[39,1120,1121],{"class":41,"line":393},[39,1122,1123],{"class":45},"    };\n",[39,1125,1126],{"class":41,"line":402},[39,1127,189],{"emptyLinePlaceholder":188},[39,1129,1130,1132,1134,1136,1138],{"class":41,"line":412},[39,1131,674],{"class":205},[39,1133,339],{"class":45},[39,1135,69],{"class":205},[39,1137,260],{"class":65},[39,1139,346],{"class":45},[39,1141,1142,1144,1146,1148,1150,1152,1154],{"class":41,"line":418},[39,1143,674],{"class":205},[39,1145,354],{"class":45},[39,1147,69],{"class":205},[39,1149,359],{"class":65},[39,1151,362],{"class":45},[39,1153,366],{"class":365},[39,1155,369],{"class":45},[39,1157,1159],{"class":41,"line":1158},35,[39,1160,189],{"emptyLinePlaceholder":188},[39,1162,1164,1166,1168,1170,1172,1174,1176,1178,1180,1182,1184],{"class":41,"line":1163},36,[39,1165,674],{"class":205},[39,1167,505],{"class":65},[39,1169,263],{"class":205},[39,1171,510],{"class":205},[39,1173,513],{"class":45},[39,1175,517],{"class":516},[39,1177,520],{"class":45},[39,1179,523],{"class":516},[39,1181,526],{"class":45},[39,1183,269],{"class":205},[39,1185,230],{"class":45},[39,1187,1189,1191,1193,1195,1197,1199,1201,1203,1205,1207],{"class":41,"line":1188},37,[39,1190,257],{"class":205},[39,1192,538],{"class":45},[39,1194,69],{"class":205},[39,1196,543],{"class":205},[39,1198,546],{"class":65},[39,1200,549],{"class":45},[39,1202,552],{"class":72},[39,1204,523],{"class":45},[39,1206,557],{"class":72},[39,1208,369],{"class":45},[39,1210,1212,1215,1217,1219,1221,1223,1225],{"class":41,"line":1211},38,[39,1213,1214],{"class":45},"      console.",[39,1216,700],{"class":65},[39,1218,362],{"class":45},[39,1220,705],{"class":72},[39,1222,517],{"class":45},[39,1224,710],{"class":72},[39,1226,369],{"class":45},[39,1228,1230,1233,1235,1237],{"class":41,"line":1229},39,[39,1231,1232],{"class":205},"      await",[39,1234,720],{"class":45},[39,1236,723],{"class":65},[39,1238,346],{"class":45},[39,1240,1242,1245,1247],{"class":41,"line":1241},40,[39,1243,1244],{"class":45},"      document.fonts.",[39,1246,733],{"class":65},[39,1248,736],{"class":45},[39,1250,1252],{"class":41,"line":1251},41,[39,1253,1123],{"class":45},[39,1255,1257],{"class":41,"line":1256},42,[39,1258,189],{"emptyLinePlaceholder":188},[39,1260,1262,1265,1267,1269,1271,1273],{"class":41,"line":1261},43,[39,1263,1264],{"class":65},"    watch",[39,1266,777],{"class":45},[39,1268,517],{"class":516},[39,1270,526],{"class":45},[39,1272,269],{"class":205},[39,1274,230],{"class":45},[39,1276,1278,1280,1282,1284,1286,1288,1290,1292,1294,1296,1298,1300],{"class":41,"line":1277},44,[39,1279,257],{"class":205},[39,1281,792],{"class":45},[39,1283,69],{"class":205},[39,1285,797],{"class":45},[39,1287,800],{"class":65},[39,1289,803],{"class":45},[39,1291,806],{"class":516},[39,1293,526],{"class":45},[39,1295,269],{"class":205},[39,1297,813],{"class":45},[39,1299,816],{"class":205},[39,1301,819],{"class":45},[39,1303,1305,1308],{"class":41,"line":1304},45,[39,1306,1307],{"class":65},"      loadFont",[39,1309,827],{"class":45},[39,1311,1313],{"class":41,"line":1312},46,[39,1314,1315],{"class":45},"    });\n",[39,1317,1319],{"class":41,"line":1318},47,[39,1320,189],{"emptyLinePlaceholder":188},[39,1322,1324,1327],{"class":41,"line":1323},48,[39,1325,1326],{"class":205},"    return",[39,1328,378],{"class":45},[39,1330,1332],{"class":41,"line":1331},49,[39,1333,1334],{"class":45},"  },\n",[39,1336,1338],{"class":41,"line":1337},50,[39,1339,564],{"class":45},[39,1341,1343,1345,1347],{"class":41,"line":1342},51,[39,1344,178],{"class":45},[39,1346,197],{"class":49},[39,1348,53],{"class":45},[39,1350,1352,1354,1356],{"class":41,"line":1351},52,[39,1353,46],{"class":45},[39,1355,407],{"class":49},[39,1357,53],{"class":45},[39,1359,1361,1364],{"class":41,"line":1360},53,[39,1362,1363],{"class":65},"#app",[39,1365,230],{"class":45},[39,1367,1369,1372,1375,1378,1380,1383],{"class":41,"line":1368},54,[39,1370,1371],{"class":365},"  font-family",[39,1373,1374],{"class":45},": ",[39,1376,1377],{"class":72},"\"Times New Roman\"",[39,1379,520],{"class":45},[39,1381,1382],{"class":365},"sans-serif",[39,1384,218],{"class":45},[39,1386,1388,1391,1393,1396],{"class":41,"line":1387},55,[39,1389,1390],{"class":365},"  -webkit-font-smoothing",[39,1392,1374],{"class":45},[39,1394,1395],{"class":365},"antialiased",[39,1397,218],{"class":45},[39,1399,1401,1404,1406,1409],{"class":41,"line":1400},56,[39,1402,1403],{"class":365},"  -moz-osx-font-smoothing",[39,1405,1374],{"class":45},[39,1407,1408],{"class":365},"grayscale",[39,1410,218],{"class":45},[39,1412,1414,1417,1419,1422],{"class":41,"line":1413},57,[39,1415,1416],{"class":365},"  text-align",[39,1418,1374],{"class":45},[39,1420,1421],{"class":365},"center",[39,1423,218],{"class":45},[39,1425,1427,1430,1432,1435],{"class":41,"line":1426},58,[39,1428,1429],{"class":365},"  color",[39,1431,1374],{"class":45},[39,1433,1434],{"class":365},"#2c3e50",[39,1436,218],{"class":45},[39,1438,1440,1443,1445,1448,1451],{"class":41,"line":1439},59,[39,1441,1442],{"class":365},"  margin-top",[39,1444,1374],{"class":45},[39,1446,1447],{"class":365},"60",[39,1449,1450],{"class":205},"px",[39,1452,218],{"class":45},[39,1454,1456],{"class":41,"line":1455},60,[39,1457,1458],{"class":45},"}\n",[39,1460,1462,1464,1466],{"class":41,"line":1461},61,[39,1463,178],{"class":45},[39,1465,407],{"class":49},[39,1467,53],{"class":45},[10,1469,1470],{},"Final Result:",[1472,1473,1474],"figure",{},[1475,1476,1477],"video",{"controls":188,"allowFullScreen":188},[1478,1479],"source",{"src":1480,"type":1481},"\u002Fcontent\u002Fresult.mp4","video\u002Fmp4",[10,1483,1484],{},"Further Reading \u002F References:",[1486,1487,1488,1496,1502,1508],"ul",{},[1489,1490,1491],"li",{},[583,1492,1495],{"href":1493,"rel":1494},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FFontFace\u002FFontFace",[587],"FontFace: MDN",[1489,1497,1498],{},[583,1499,1501],{"href":857,"rel":1500},[587],"Document Fonts List",[1489,1503,1504],{},[583,1505,1507],{"href":585,"rel":1506},[587],"Vue Watch",[1489,1509,1510],{},[583,1511,1514],{"href":1512,"rel":1513},"https:\u002F\u002Fv3.vuejs.org\u002Fapi\u002Frefs-api.html#refs",[587],"Vue Ref",[407,1516,1517],{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":35,"searchDepth":56,"depth":56,"links":1519},[],"2021-08-11","Load a web font on demand with the CSS Font Loading API. Build a FontFace in JavaScript, await its load, add it to document.fonts, and skip the fonts a page never shows.",false,"md","2026-08-29T17:42:32+07:00",{},"\u002Fblog\u002Fdynamic-font-loading","4 min read",{"title":5,"description":1521},"blog\u002Fdynamic-font-loading","f4103yZPesqwcnemKGGiNIPbnwPdQos6-O2FcMEa7cQ",1788101292858]