JavaScript/CSS Font Detector

JavaScript code to detect available availability of a particular font in a browser using JavaScript and CSS.

Update: I have updated the algo of the script and it is almost 100% accurate.

This JavaScript class can be used to guess if a particular font is present in a machine. This may be help of desktop-like web application developers when they want to provide different skins or fonts preferences to their users. This may also be help for blog skin designers which can provide different fonts for different users based on the list of fonts on their machine. Designers don’t have to rely on the most common fonts like Arial, Verdana or Times New Roman. Since increasing number of users
have modern PC with new operating system / applications, they may very well have a wide array of other common fonts in their machine.

How does it work?

This code works on the simple principle that each character appears differently in different fonts. So different fonts will take different width and height for the same string of characters of same font-size.

Widths of same text in different fonts

We try to create a string with 3 generic font-face, monospace, sans-serif and sans and note their width. Then try to create the same string in HTML using the font to be tested and the generic fallback font. If the font-face is not available, it takes up the generic fallback font-face. We then compare the width of the string with the new font and width of the string with the fallback generic font-face, if they are different, then the font exists, otherwise not.

<span style="font-family: monospace; font-size: 72px">mmmmmmmmmmlli</span>
vs.
<span style="font-family: New-Font, monospace; font-size: 72px">mmmmmmmmmmlli</span>

Since this test is repeated three times against 3 font families, it gives almost 100% accurate results. The string which we will use to generate the widths can be anything. But I guess we use ‘m’ or ‘w’ because these two characters take up the maximum width. And we use a trailing ‘l’ and ‘i’ so that the same width fonts-faces can get separated based on the width of l character. I have tested it on Firefox, IE, Opera, Safari, Chrome

Note:
It required to execute the script after its completely loaded for some browsers like Opera. (Opera cannot calculate the offsetWidth until all the parents are completely loaded)

Download ver 0.3 (24 Mar 2012)

Released under Apache Software License 2.0.

Plain text JS code (v0.3)

Demo

You can test any Font here:


// Usage
window.onload = function() {
    var detective = new Detector();
    alert(detective.detect('font name'));
};

Fonts on your computer

This table below shows which fonts are present on your system. (I have listed some of the most common and some uncommon fonts.)

Font Name Detected?

• • •

23 Responses to JavaScript/CSS Font Detector

  1. Rodrigo says:

    This approach is quite innovative!

  2. David Ruiz says:

    Cool! Great idea compare font sizes. But I had problems with Firefox:

    When Firefox don’t find the font, not always shows ‘sans-serif’ type. Changing next line solves it:
    f[0] = s.style.fontFamily = font;
    to
    f[0] = s.style.fontFamily = font + “, sans-serif”;

    Anyway, good work.

  3. _asterix_ says:

    Wow! This is a gerat Solution. Thank you very much.

  4. Emlyn says:

    OS X 10.5 using FF 3.5.7 and all testing works fine (including Calibri).

    Great temp fix until CSS3 is in play–tx.

  5. Darryl Booms says:

    May I suggest adding single quotes around the font name when setting for the test font. Firefox 3.6.3 at least is omitting the “font-family: ” part if there are spaces in the name for at least the “Free 3 of 9 Extended” from http://www.barcodesinc.com/free-barcode-font/ and may be playing a part in some of the other issues too. Plus it still detects just fine (on Firefox 3.6.3 & IE 8) with the extra single quotes.

    f[0] = s.style.fontFamily = font; // Name of the font
    changes to
    f[0] = s.style.fontFamily = “‘” + font + “‘”; // Name of the font

  6. Bronius says:

    I think this font detector is great for installed fonts but doesn’t seem to do it for fonts downloaded by @font-face, does it? This applies to folks who have disabled font downloading in IE security options.

    Thanks for the great post.

  7. Bronius says:

    [edit] Oh snap! I was testing incorrectly. YES, this font detector detects even when a font is downloaded to the client browser using the @font-face css rule and effectively provides a work-around for Internet Explorer users whose security settings disable font downloads. THANK YOU :D

  8. Rupi says:

    Thanks, great script !!!
    It might be usefull some time

  9. moto kurye,istanbul kurye,acil kurye says:

    I delight in, lead to I found just what I was having a look for. You have ended my four day lengthy hunt! God Bless you man. Have a great day. Bye

  10. The idea doing it this way is nice, but not really reliable enough if you need a near 100% solution. Different rendering of browsers and of course different font smoothing and subpixeling methods will add an – from javascript perspective – blackbox.

    Sure, if you render the font large, these “jitter” will be smaller in relation to the font itself but it is not zero. Also important to know is, that there might exist customized corporate fonts which mostly have identical metrics to the source font but may be different in certain details. It is impossible to surely detect those fonts by simply measuring a string containing only 3 different faces of it.

    Sure, in most cases this doesn’t happen and asking the question why would someone choose to use those fonts on a webpage may be understandable. But it might happen for some reason – e.g. in a near-wysiwyg-scenario for customizing print products without plugin technology or if some intranet stuff uses fonts to implement the corporate design without relying on cufon or sifr for some reason.

    You can reduce the gap and increase accuracy for firefox or opera etc for example, if you query the computed style for these browsers. If you set a particular font and it does not exist, normal behaviour means to use a default font. Unfortunately getting the computed style in IE won’t be possible yet as far as i know (you might try to play with element.currentStyle in IE – i didn’t do this until now).

    Anyhow your solution delivers surprisingly exact results with a view on it’s simplicity and therefore it might for most cases a good and specially easy to implement and small footprint compromise to perform font detection.

    • Lalit says:

      Alex,
      Thanks for the feedback.
      I am also working on a solution which will be 100% sure in matching the font names. I will post it soon on my blog.

    • Lalit says:

      Alex,

      I have uploaded a new version of my script. This should be almost 100% fool proof solution. Let me know your thoughts.

      • Axel Napolitano says:

        Hi Lalit,

        sounds interesting. I am curious to see and test the updated version as soons as it is available.

        Best regards,

        Axel

  11. Shahid Faraz says:

    Worked great. :D
    Thank you very much. :)

  12. Dave Hein says:

    You have the three default fonts as monospace, sans-serif, and sans. As in:

    var baseFonts = ['monospace','sans-serif','sans'];

    But I think you should change the last one to “serif” instead of “sans”. Like this:

    var baseFonts = [‘monospace’,’sans-serif’,‘serif’];

  13. Chris Morrow says:

    Thanks for sharing your work. Finally a way using JS only to detect system fonts. I still wish you could get all system fonts without specifying a font-family to detect all fonts installed as you can do with Flash and Java.

  14. Sagar says:

    Hi,
    Will this script work even on Android. Because When I ran it on android, it gave me true for all the fonts and I do not have some of those fonts in android at all.
    Any idea?

  15. Seems to be a discrepancy between Firefox Mac and -webkit Mac browsers…

    Your on-page demo hero in Safari correctly detects Courier New. Firefox reports it as not avialable (“false”).

    To this same effect, testing for “HelveticaNeue-Light” in a -webkit browser reports “true” when it is present, but the same font-name reports false in Firefox – on the same computer.

    “Helvetica Neue” however is found “true” on Firefox, however.

    The webpage even renders ‘HelveticaNeue-Light’ in Firefox correctly, but only when set using an @font-face src: local(‘HelveticaNeue-Light’); rule.

    How is your script handling font names with dashes/spaces? How about when the font is only available through the src: local() syntax? And why would Safari be able to find the Helvetica Neue’s font face, “Light” when Firefox can’t?

    Would love to get to the bottom of this. Thanks for your script!

  16. Adamo says:

    Still wondering about Firefox vs. Chrome and why one picks up fonts like “Helvetica Neue Light” and the other doesn’t, when the font is installed and the browsers are on the same system (Mac). Please see my earlier comment (in moderation) for more details. Thanks.

  17. Luke says:

    Brilliant. Absolutely brilliant.

  18. Jake Wilson says:

    Damn this script is brilliant. I used it to solve a problem regarding trying to load a webfont that was going to be used in markup. Because browser load web fonts asyncronously, the javascript that drew the canvas would run before the web font was finished loading, therefore causing the browser to use either a fallback font in Firefox or not show any font at all in Chrome. Using this font detector, I was able to programatically choose which font to use in the Canvas, depending on if the web font was finished downloading. If the user’s browser hadn’t downloaded the webfont yet, their canvas would use a default fallback font. But the next time they loaded the page, it would use the proper font since it was cached in their browser by then. Seriously, really slick script…