Chanwoo Park
Chanwoo Park

Reputation: 246

Is there a way to determine when font family being actually rendered

Is there a way to determine when font style is being actually rendered? early stage of breakpoint

having break point on early stage (which is right after DOM is created) shows that the paragraph's font family value is font 'Montserrat-Bold' which is added via @font-face css but an actual rendered display shows as default font.

break point after some amount of time

Here, break point after some amount of time shows that the paragraph element is actually styled (using font family) as it is to be expected.

I assume there's a process where browser actually renders (or apply) font style. Is there a way to know or to detect when that happens?

Upvotes: 5

Views: 1054

Answers (1)

herrstrietzel
herrstrietzel

Reputation: 17215

Unfortunately there is no direct way (e.g. via CSS Font Loading API) to get the actually rendered font-family.

Workaround

  1. Check the applied font-families via getComputedStyle(el).fontFamily
  2. Check if fonts are loaded via FontFaceSet.check() Unfortunately, the check() method also returns true if a font doesn't exist. So it's not a reliable way to check all available fonts.

Example:

let info = document.querySelector('.info');
let textEls = document.querySelectorAll('h1, p, pre');
// check fonts - Monserrat is not yet available
let usedFonts = checkAppliedFont(textEls);

function checkAppliedFont(textEls){
  let usedFonts = [];
  textEls.forEach(function(el,i){
    let nodeType = el.nodeName.toLowerCase();
    let fontFamily = getComputedStyle(el).fontFamily;
    let familyArr = fontFamily.split(',');
    let fontApplied = false;
    let renderedFont = '';
    for(let i=0; i<familyArr.length && !fontApplied; i++){
      let currentFamily = familyArr[i];
      fontApplied = document.fonts.check(`12px ${currentFamily}`);
      if(fontApplied){
        //font is loaded - return family name
        renderedFont = currentFamily;
      }
    }
    usedFonts.push({ type:nodeType, font: renderedFont});
  })
  info.innerText = JSON.stringify(usedFonts)
  return usedFonts;
}


let fontUrl =  "https://fonts.gstatic.com/s/montserrat/v24/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw5aXo.woff2";
let fontFamily = "Montserrat";
let fontOptions = {
  weight: 400,
  style: "normal"
};

let webfont = '';
async function loadFonts() {
  const font = new FontFace(fontFamily, `url(${fontUrl})`);
  font.weight = fontOptions.weight ? fontOptions.weight : 400;
  font.style = fontOptions.style ? fontOptions.style : "normal";
  // wait for font to be loaded
  await font.load();
  webfont = font;
  document.fonts.add(font);
  checkAppliedFont(textEls);
}

function unloadFonts(font) {
  document.fonts.delete(font);
  checkAppliedFont(textEls);
}
h1{
  font-family:"Montserrat", Georgia;
  font-weight:400;
}

p{
  font-family:"Montserrat", Arial
}

pre{
  font-family:"Montserrat", monospace, sans-serif;
  background:#eee;
}
<button onclick="loadFonts()" type="button">Load font</button>
<button onclick="unloadFonts(webfont)" type="button">Delete font</button>
<h1>Should be Monserrat 1234</h1>
<p>Paragraph text.</p>
<pre>Pre text.</pre>
<p class="info"></p>

The above example will loop through all font-families specified in css rules (retrieved via getComputedStyle()).
E.g font-family:"Montserrat", monospace, sans-serif
Fonts that are not available will be skipped. The first available font is probably the rendered font.

Depending on your OS or browser, this workaround might fail to get the actually applied/rendered font.

Upvotes: 1

Related Questions