10

Google Chrome displays the rendered font in the DevTools.

For example, given:

font-family: Montserrat, Helvetica, sans-serif;

and the Montserrat font is missing/disabled, Chrome tells us that Helvetica is being rendered:

enter image description here

Is there a way to get the rendered font in JavaScript? (even if it just works in Chrome)


Notes:

  1. This solution suggests getComputedStyle(...).fontFamily, but it returns the CSS declaration "Montserrat, Helvetica, sans-serif", not the actual rendered font.
  2. This solution uses puppeteer, but I couldn't figure out how to achieve the same purely in DevTools (without puppeteer).
Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746
  • 1
    What about solution by @julien-cabanes : https://jsfiddle.net/JulienCabanes/ubzrmmy5/ – Pavel Třupek Sep 09 '19 at 11:44
  • Maybe I'm missing something, but `getComputedStyle(...).fontFamily` just returns the CSS declaration, not the actual rendered font. https://jsbin.com/nojatiboho/1/edit?html,css,js,output – Misha Moroshko Sep 09 '19 at 12:05
  • 1
    As far as I know, it is not possible. But that info is a few years old, so it might have changed. – André Reichelt Sep 09 '19 at 12:10
  • check the other answers, they provide some workaround, the accepted answer isn't correct – Temani Afif Sep 09 '19 at 12:10
  • 1
    @TemaniAfif I couldn't find an answer there that works reliably. – Misha Moroshko Sep 09 '19 at 13:25
  • 2
    not sure if such solution exist, you will only find *hack* and workaround. In all the cases, the question reamain a duplicate. If there is a new accurate solution it should go there. You may consider adding a bounty there. – Temani Afif Sep 09 '19 at 13:28
  • I wonder if you can style an element using different fonts available in your `font-family` and then [take a "screenshot"](https://medium.com/@danielsternlicht/capturing-dom-elements-screenshots-server-side-vs-client-side-approaches-6901c706c56f) and compare the results to see which one matches?! – Gezim Sep 09 '19 at 19:25
  • 2
    Duplicate of https://stackoverflow.com/questions/7444451/how-to-get-the-actual-rendered-font-when-its-not-defined-in-css Not sure why it got reopened... – Kaiido Sep 15 '19 at 13:08
  • What is you use case exactly? You might have better answers based on that, and it might be easier to differentiate yours from previous questions. – Kaiido Sep 15 '19 at 13:39

2 Answers2

5

It is still not possible to access this information from Web-APIs.

There is an ongoing discussion in the Houdini group about including a font-metrics API, that is supposed to include something like that, but it's still not even proposed as a spec draft and there will be a lot of burden on the road.

What font(s) are being used? This is complicated because multiple fonts can be used per paragraph, per line, per word, and even per glyph. The fonts should be exposed in the form of handles with complete font information, and (for web fonts) a handle to the raw font data. dbaron & eae are going to own this area and propose an API.

Indeed, one could have one font for the glyph ̂ (U+0302), and another one for the glyph a (U+0061) which would make the combined glyph would actually use two different fonts.

Current discussions seem to point to a Font interface available from document.measureElement and document.measureText methods. This interface would expose two properties: a DOMString name, and a number glyphsRendered. However, once again these are still discussion and still not yet proposed as drafts, a lot of discussion is still to be made and I wouldn't hold my breath waiting for it to be implemented anywhere any time soon.


Now, there are hacks, like numerous other Q/A already told don't stick to the accepted answer there, implying looking at the size of the rendering for the simplest, and looking at the rendered pixels for the more advanced ones, but being hacks, they won't work in every cases.
For instance, I could have a custom font on my system that would render only some characters borrowed from a well-known font, no such hack would be able to tell if the browser did fallback to that font or the actual well-known one.

The only way to know for sure is to keep the control and use web-fonts.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • `no such hack would be able to tell if the browser did fallback to that font or the actual well-known one` — I suppose with further hacking you could simply clone the element, replace the text with all necessary unicode characters, then analyze them all and compare. This would be very slow though I'd imagine, although compared to how much RAM Chrome already consumes it might not be too bad afterall, lol. – Albert Renshaw Jul 10 '22 at 03:09
  • @AlbertRenshaw What I meant with this sentence is that by only analyzing the rendered pixels you can't tell if the glyph was rendered using "My-clone-of-Times-New-Roman" or using the real one, since both would produce the same exact pixels. The only solution would be to analyze the binary font files directly (.woff, .otf, .ttf etc.) – Kaiido Jul 10 '22 at 03:24
0

Since no one had suggested it yet, there would be one more way to find out which font is rendered.

The snippet below gets the font-family CSS definition in use for the element (or of course you can hardcode the font-family names if you want) and checks in order, whether the font family is loaded and returns the name of the first loaded font family.

Since the font-family CSS property specifies a prioritized list of one or more font family names, the first available font is very likely also the rendered font. Snippet uses the CSS Font Loading API, which is well supported (but not in IE of course) https://developer.mozilla.org/en-US/docs/Web/API/CSS_Font_Loading_API

For example, let's imagine that the CSS would be:

.body { 
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif;
}

Snippet

const getRenderedFontFamilyName = ( element ) => {
    // Font families set in CSS for the element
    const fontFamilies = window.getComputedStyle( element, null ).getPropertyValue( "font-family" );
    // const hardcodedFamilies = '-apple-system, BlinkMacSystemFont, "Segoe UI Adjusted", "Segoe UI", "Liberation Sans", sans-serif';
    
    // Remove the " sign from names (font families with spaces in their names) and split names to the array
    const fontFamiliesArr = fontFamilies.replaceAll('"', "").split(", ");

    // Find the first loaded font from the array
    return fontFamiliesArr.find( e => document.fonts.check( `12px ${e}`) );
}

Example how to get rendered font-family of StackOverflow body:

getRenderedFontFamilyName(document.querySelector('body'));
vilu
  • 21
  • 5