Home > front-end development, javascript, typography > @font-face feature detection

@font-face feature detection

August 20th, 2009

As I'm piecing together a very comprehensive solution for using custom typefaces online, one of the crucial aspects is determining what browsers support @font-face.

My requirements for this detection were:

  • No browser userAgent sniffing
  • No extra HTTP request required
  • The test must be synchronous, no race conditions or HTTP requests
  • Must be performant with a small footprint, natch
  • Results should match the latest research on compatibility

I quickly tried:

!!window.CSSFontFaceRule

This test works great in FF2+, Safari and Opera. But it fails in IE (bug surprise) and Chrome gives a false positive.

The code

What follows is the best test for @font-face support I have found:

 
/*!
 * isFontFaceSupported - v0.9 - 12/19/2009
 * http://paulirish.com/2009/font-face-feature-detection/
 * 
 * Copyright (c) 2009 Paul Irish
 * MIT license
 */
 
var isFontFaceSupported = (function(){
 
 
    var fontret,
        fontfaceCheckDelay = 100;
 
		// IE supports EOT and has had EOT support since IE 5.
		// This is a proprietary standard (ATOW) and thus this off-spec,
		// proprietary test for it is acceptable. 
    if (!(!/*@cc_on@if(@_jscript_version>=5)!@end@*/0)) fontret = true;
 
    else {
 
    // Create variables for dedicated @font-face test
      var doc = document, docElement = doc.documentElement, 
          st  = doc.createElement('style'),
          spn = doc.createElement('span'),
          wid, nwid, body = doc.body,
          callback, isCallbackCalled;
 
      // The following is a font, only containing the - character. Thanks Ethan Dunham.
      st.textContent = "@font-face{font-family:testfont;src:url(data:font/opentype;base64,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)}";
      doc.getElementsByTagName('head')[0].appendChild(st);
 
 
      spn.setAttribute('style','font:99px _,serif;position:absolute;visibility:hidden'); 
 
      if  (!body){
        body = docElement.appendChild(doc.createElement('fontface'));
      } 
 
      // the data-uri'd font only has the - character
      spn.innerHTML = '-------';
      spn.id        = 'fonttest';
 
      body.appendChild(spn);
      wid = spn.offsetWidth;
 
      spn.style.font = '99px testfont,_,serif';
 
      // needed for the CSSFontFaceRule false positives (ff3, chrome, op9)
      fontret = wid !== spn.offsetWidth;
 
      var delayedCheck = function(){
        if (isCallbackCalled) return;
        fontret = wid !== spn.offsetWidth;
        callback && (isCallbackCalled = true) && callback(fontret);
      }
 
      addEventListener('load',delayedCheck,false);
      setTimeout(delayedCheck,fontfaceCheckDelay);
    }
 
    function ret(){  return fontret || wid !== spn.offsetWidth; };
 
    // allow for a callback
    ret.ready = function(fn){
      (isCallbackCalled || fontret) ? fn(fontret) : (callback = fn);
    }  
 
    return ret;
})();

Download from github

The latest is always at: http://github.com/paulirish/font-face-detect
isFontFaceSupported.js Uncompressed – 4.3k
isFontFaceSupported.min.js Compressed – 3.1k

Usage

isFontFaceSupported() // will return a boolean indicating support
 
// you can also use with a callback,
//  it will be called 100ms later which is adaquate for Gecko and Webkit to properly use the data-uri'd font.
isFontFaceSupprted.ready(function(bool){
  // bool is a boolean that indicates support
});

Sorry. :(

You'll spot the IE conditional compilation in there. I don't like it either, but I'm unaware of any other workable approach (that doesn't pull in an .eot) to test for @font-face support. If you have an idea, please share it!

On the approach

I first use the Web Font Optimizer to subset a truetype font to only contain the period (.) character (2.2k file!), then send it through a data URI converter, then chuck it into a style tag. I test the width of a span of text without the custom font, and then again with the custom font. If the values are different, we can assume @font-face is supported and works.

With a trip through the YUI Compressor, the script is 3.5k3.1k. If you have any ideas on bringing that figure down, I'd love to hear 'em.

Great! Any disadvantages?

Yeah there's one big one. Both Gecko and Webkit load in a data-uri font asynchronously, so the test may give a false negative if you call isFontFaceSupported() immediately afterwards:

<script src="isFontFaceSupported.min.js"></script>
<script>
  if (isFontFaceSupported()) ... // this may report a false negative.
 // that's why we have the isFontFaceSupported.ready() callback mechanism

I'm not terribly happy with this asynchronous delay, so I've written an alternative that uses browser userAgent sniffing. This practice is not recommended and is not terribly future-proof, but it's the only synchronous solution available.

isFontFaceSupported() – sniffing variant
/*!
 * isFontFaceSupported - Sniff variant - v0.9 - 12/19/2009
 * http://paulirish.com/2009/font-face-feature-detection/
 * 
 * Copyright (c) 2009 Paul Irish
 * MIT license
 */
 
/* Browser sniffing is bad. You should use feature detection.
   Sadly the only feature detect for @font-face is 
   asynchronous. So for those that *need* a synchronous solution,
   here is a sniff-based result:
*/
 
var isFontFaceSupported = function(){
 
  var ua = navigator.userAgent, parsed;
 
  if (/*@cc_on@if(@_jscript_version>=5)!@end@*/0) 
      return true;
  if (parsed = ua.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/))
      return parsed[1] >= '4.0.249.4';
  if ((parsed = ua.match(/Safari\/(\d+\.\d+)/)) && !/iPhone/.test(ua))
      return parsed[1] >= '525.13';
  if (/Opera/.test({}.toString.call(window.opera)))
      return opera.version() >= '10.00';
  if (parsed = ua.match(/rv:(\d+\.\d+\.\d+)[^b].*Gecko\//))
      return parsed[1] >= '1.9.1';    
 
  return false;
 
}

This guy is also on github

2009.09.24: updated the code, and threw it all on github. callback style makes its debut here. This code matches the exact same implementation that's in Modernizr 1.0

2009.12.18: Added a useragent sniffing alternative for those who want reliable synchronous detection.

2009.12.19: New, smaller font file (Thanks Ethan Dunham). The file is now 15% smaller. Script does not remove the extra element it adds to the DOM now, as to assure more accurate results.

2010.11.02: I now recommend a different technique.. It's from Diego Perini.. The code is below:
var isFontFaceSupported = (function(){  
var 
sheet, doc = document,
head = doc.head || doc.getElementsByTagName('head')[0] || docElement,
style = doc.createElement("style"),
impl = doc.implementation || { hasFeature: function() { return false; } };
 
style.type = 'text/css';
head.insertBefore(style, head.firstChild);
sheet = style.sheet || style.styleSheet;
 
var supportAtRule = impl.hasFeature('CSS2', '') ?
        function(rule) {
            if (!(sheet && rule)) return false;
            var result = false;
            try {
                sheet.insertRule(rule, 0);
                result = !(/unknown/i).test(sheet.cssRules[0].cssText);
                sheet.deleteRule(sheet.cssRules.length - 1);
            } catch(e) { }
            return result;
        } :
        function(rule) {
            if (!(sheet && rule)) return false;
            sheet.cssText = rule;
 
            return sheet.cssText.length !== 0 && !(/unknown/i).test(sheet.cssText) &&
              sheet.cssText
                    .replace(/\r+|\n+/g, '')
                    .indexOf(rule.split(' ')[0]) === 0;
        };
 
return supportAtRule('@font-face { font-family: "font"; src: "font.ttf"; }');
})();

Paul Irish front-end development, javascript, typography

  1. August 20th, 2009 at 17:24 #1

    The width checking technique I'm using has been around for a bit: [1], [2], [3].

    Of course there is the potential for an edge case where a monospaced font will match the exact same width as the custom font, thereby returning a false positive. It's pretty much inconceivable, though. :)

  2. August 21st, 2009 at 10:26 #2

    Awesome trick. I really like the low-dependency of the script with that data URI business. Keep up the great work!

    The data URI really brings the file size up, which is unfortunate. Since the glyph itself doesn't matter, would there be any way to generate *some* valid base64 string in javascript that would take less space but read as a valid glyph, and then just parse it into the style text?

    It's already a win in my opinion, but if we (read: 'you') could get that data URI size down, there would be no reason for this to not be the defacto standard.

  3. August 21st, 2009 at 13:18 #3

    Maybe a simpler glyph, like space or em-dash, will render smaller!

  4. August 21st, 2009 at 13:21 #4

    I got a pretty good fix, now.

    Wordpress chokes on the characters, so here's the paste:
    http://dpaste.com/hold/83685/

    Cuts the size in half, basically. :) Thx for the idea Alex.

  5. August 21st, 2009 at 13:58 #5

    A little bit more detail on the font width edge case…

    Monospace will certainly give a much wider period character than any non-monospace font. For instance, with the code above, in Safari 4, the monospace text is 64px wide… the @font-face is only 24px wide; so there's quite a large delta.
    That means that as long as no computer has a default monospace glyph base of 3px, the test will be fine. :)

  6. August 24th, 2009 at 22:19 #6

    wow, nice solution, way better than my solution which relied heavily on jQuery and a jQuery plugin, thanks for the tips :)

  7. August 31st, 2009 at 18:14 #7

    I changed the test to use serif instead of monospace as I found an unreported bug in Gecko where fontFamily = 'notafont,monospace' will give different results from 'monospace'.
    (And this script recommends against sans-serif)

  8. EmImE
    September 1st, 2009 at 21:49 #8

    Hi – really interesting idea, but it's not working for me in FF 3.5.2 on Linux. The script you pointed to in the previous comment mentions a bug with FF3+ not falling back to the parent's font face if the element's font-face doesn't exist. (Listed under the latest update) This may the cause of the problem. Unfortunately, I don't have time right now to debug it myself, but I did want to give you a head's up.

    Anyway, thanks for sharing your code!

  9. September 15th, 2009 at 20:03 #9

    @EmImE Hiya.

    I've changed the script since I posted it (but havent updated it here just yet)

    Can you go to http://www.modernizr.com/ and tell me if there's a green check next to @font-face in the middle. If there is, then my new approach works.
    If not, then we're in trouble. :/

  10. EmImE
    September 21st, 2009 at 16:45 #10

    I do see the check. I'd love to see the solution, so please post it when you get a chance! Thanks!

  11. Lampica
    November 13th, 2009 at 01:34 #11

    How will this be effected by the NoScript addon for Firefox which blocks @font-face by default. Will your script correctly report lack of support if NoScript blocks @font-face?

    Regarding the ie conditional comments, it raises the question of how accurate this test is. What if they have IE but they have somehow disabled @font-face support? I would really like something that is completely reliable. Maybe you could go ahead and include the .eot file and make sure that @font-face support is working in ie rather than assuming it is, or do it as a separate version or something.

    I would really like to be able to send a default-no-font.css file to style the page as if no @font-face support is present. Then check to see if @font-font face support exists and if it does to run font-face-rules.css to send the fonts via @font-face and then run the font-enhanced.css file which will adjust some styles from the default to enhance the appearance of the page for the custom fonts.

    The most important thing though is that I don't want to load that last file (font-enhanced.css) unless I am absolutely certain that @font-face is working. If there is any doubt whatsoever then I don't want to activate that last file. Is there any way to double check after the fonts have been sent, that they were received?

    Is this going to run on every page refresh? Is there a way to make it so that once you know the fonts are working for a client you could stop checking for a little while?

  12. Lampica
    November 16th, 2009 at 10:25 #12

    hehe, sorry. I realize how ridiculous that question was. obviously NoScript would just block your script and thus it would not be able to correctly report anything.

    I really wish that @font-face didn't need to be tied to JS. As standard CSS, supported by the vast majority of browsers, it shouldn't require JS.

    But between NoScript blocking it by default, and that minority of other browsers that don't support it – most who would care to use it to its full potential will still need to provide fallback. It is unfortunate that we must use JS to provide a pure CSS fallback for a pure CSS feature.

    Just in order to make some minor CSS adjustments for when it is not supported, we have to tie it to JS. Have the default be "not supported" and only if the JS runs, then use @font-face and style the page accordingly. When really the @font-face should be fine without JS..

    But what about PHP? Couldn't you run the same kind of single-letter size test with PHP?

  13. November 30th, 2009 at 01:00 #13

    @Lampica
    So this check is mostly useful for detecting when a browser *doesn't* support @font-face; so you can create a proper fallback.

    A browser that doesn't support it won't download the font data so you're not wasting bytes or anything.

    No you can't test this in PHP.

  14. Lampica
    December 2nd, 2009 at 22:32 #14

    Thanks for the reply Paul. I guess I understand. Personally I would rather use it the other way around though. To detect whether it is supported and then only if it is supported send the fonts – so the default is the fallback. If you use it as you suggest (just to detect lack of support and provide fallback) then anyone with JS disabled who can't support @fontface will neither get your fonts nor the fallback (presently anyone running FF with ScriptBlocker fits this description because ScriptBlocker blocks both JS and @fontface by default).

    So for me it makes much more sense to provide the fallback as default and then detect @fontface support and only if it is supported then to provide the fonts and make a few CSS tweaks as needed.

    No real problem there either. Your script should work fine for this. However, it just means that a minority of people who have JS disabled but actually CAN support @fontface will not get the fonts. Not a major concern really. I guess it just bugs me on principal, to have the non-js @fontface standard CSS tied to JS.

    It also bugs me on principal that the creators of ScriptBlocker (a fairly popular FF addon) decided to block this standard CSS by default – I think it sets a very disturbing precedent because CSS as a standard should not be broken up to have select (standard) aspects blocked. If CSS is not supported then the fallback is pure semantic HTML which is acceptable because at least all the content is presented in an organized, readable manner. But if part of my CSS is blocked but part of it works fine then that could easily end up being a disorganized, unreadable mess. Of course just blocking @fontface is not such a big deal in and of itself but I think it sets an unfortunate precedent.

    It is funny because just before I found your script I had asked on a forum how to detect @fontface support with JS. Everyone said "impossible" which I found frustrating because, though I am not versed in JS, I KNEW that there HAD to be a way. Whether that meant using ajax or something on the server side to detect whether they DLed the font or some other kind of work around, I just knew there must be a way. No no.. Simply impossible according to numerous replies. In frustration I went to Google and found your script in like 1 minute and everyone on the forum just shut up. Now none of them will talk to me or reply to my posts at all (I guess they don't like eating their words), which sucks because I still need help configuring the script.

    I am not in a big hurry on this as (for the time being) @fontface is just something I am experimenting with for fun and interest, not for any clients. If you have the time someday though I would be very grateful if you could give us a little more detail on actually using the script (like spelled out for dummies). I guess isFontFaceSupported() // is the important thing, but I don't really know how to use this.

    What I want to do is simple.. Run your script at the end of my document (so default styles load first as the fallback), check for support, if @fontface is supported then apply a single additional .CSS file, if it is not supported then do nothing (since default fallback style has already been applied).

    Thanks a lot Paul, it is an awesome script – now if I can just make it do what I want..

  15. December 3rd, 2009 at 10:07 #15

    @Lampica
    I'm a little confused because if @font-face is not supported, the fonts won't be downloaded. (For instance in Firefox 3.0 and Chrome 3).. So I think you're getting your desired behavior for free.

    I'm assuming of course that you're just linking to ttf/otf/eot in the @font-face declaration. I would recommend putting that in your normal CSS file. Not a lot of reason to create a unique file just for it.

  16. Lampica
    December 3rd, 2009 at 22:02 #16

    Yes, just ttf/otf/eot.

    The fonts won't be downloaded if there is no support, but neither will the fallback if JS is disabled.

    What I am doing really depends on those fonts. It is a tight layout and it can deal with the slight variations in how the browsers render the fonts but if it gets a fallback font things will break (because there is no fallback fonts that have sizing anywhere close to the fonts I am using). So for a fallback I need to make some additional tweaks to the CSS to make the some aspects of the layout a little more flexible (or another option would be to swap out some bits of text with image replacements).

    I assume that others also want a more tightly controlled fallback option than just the the default CSS fallback fonts (or else why would your script even be needed?)

    So I don't want those fonts (and associated styles) loading unless I can absolutely provide a fallback should they fail. But I can only provide the fallback if JS is enabled. What if JS is not enabled but there is also no @fontface support. It seems to me that the best option is to only serve the fonts (and associated styles) if I am certain they will work and the only way to be certain is if JS is enabled.. So, I make no-fonts the default and if your script can detect support, only then send the fonts (and associated styles).

    Currently if I have ScriptBlocker active in FF 3.5.5. then both JS and @fontface will be disabled by default. So when I go to a site using your script as (in the manner you propose) I will not get their fonts and they will not be able to detect that I did not get their fonts (because of no JS) and thus no fallback will be provided either.

    It is really all academic though because what I want to do is very simple. Run your script, if it detects @fontface support then run one CSS file, if it doesn't detect @fontface support then do nothing.

    You did all the work but it is over my head. I am quite good with CSS and HTML for a graphic designer but JS is really way over my head – unless there is very clear usage instructions for dummies. ;-)

    Don't worry if you don't have the time or inclination to help me with this though, you have done so much already just by creating the script. Eventually I will get someone on a forum somewhere to help me set it up, and I am not in a big rush on this one.

  17. December 4th, 2009 at 00:17 #17

    @Lampica
    I understand better now, given the explanation of how the fallback fonts dont work.

    I'd recommend using Modernizr: http://www.modernizr.com/
    It has the same detection built into it but it's got some nice CSS hooks:
    http://www.modernizr.com/docs/#s2.1

    so you can write one font stack for browsers with @font-face support, and one for without:
    .fontface h1 { font-family: customfont, serif; size: 20px; }
    .no-fontface h1 { font-family: Verdana, sans; size: 14px; }

    Naturally, without javascript or with NoScript this is not going to work too well.. :)

  18. Lampica
    December 4th, 2009 at 01:16 #18

    But paul, that still doesn't address my concerns (though Modernizr is certainly fantastic – and I will likely have use for it in the future).

    1: I want to know whether or not @fontface is supported.

    2: I only want to use @fontface (and associated styles) if I am sure it will work. Meaning I want a fallback that will work even without JS.

    3: If JS is disabled then I can not know whether @fontface will work or not. Therefore, if JS is disabled I do not want to use @fontface.

    So I still stand by my original plan which is to..
    A: run your script.
    B: check for support.
    C: If support exists apply a single CSS file.
    D: If no support exist do nothing.

    You see, this way (and only this way), can I know with some degree of certainty that my page will look just as I want it to, no matter whether @fontface is supported AND no matter whether JS is supported. Because if JS is disabled then they get the default no-font version (which I have styled to look fine without the fonts), and if JS is enabled then I can run the check and provide the with-fonts version only if I'm sure it will work.

    I realize that your original vision here was to detect LACK of support and provide fallback, but there is no reason at all why it can't work the way I have outlined which is to check FOR support and then provide enhancement. I don't think your script would need to be changed at all here. I just need to check that Boolean and then load or not load a CSS file based on the results of the check. I just don't know the syntax to do that (it should only be a few lines of JS though).

    Thank you very much for all your patience and consideration here. I know I can be a real pain in the neck sometimes.

  19. December 4th, 2009 at 01:24 #19

    gotcha. :)

    this may or may not work…

    isFontFaceSupported.ready(function(isSupported){
        if (isSupported){
            var css = document.createElement('link');
            link.rel = 'stylesheet';
            link.type = 'text/css';
            link.href = 'http://example.com/fontface.css';
            document.body.appendChild(link);
        {
    });

    Good luck, Lampica!

  20. Lampica
    December 4th, 2009 at 04:33 #20

    AWESOME!! You are my new ultimate hero..

    I can't test it right now but I am pretty sure that is exactly what I was searching for. And even if it doesn't work that is enough for me to run with.

    Thanks so much Paul, you are a gentleman and a scholar.

  21. Adam
    January 15th, 2010 at 14:58 #21

    Thanks for all your work, it will change web design forever once accepted.

    I've just painstakingly worked out that while Opera, IE, Chrome, etc all allow relative paths like ../ or fonts/ to locate the font files, Firefox won't have it at all.

    Eg.

    @font-face {
    	font-family: 'dearJoeItalic';
    	src: url('DEARJI_.eot');
    	src: local('dearJoe Italic'), local('DearJoeItalic'), url('DEARJI_.woff') format('woff'), url('DEARJI_.ttf') format('truetype'), url('DEARJI_.svg#DearJoeItalic') format('svg');
    }
     
    Is fine, but...
     
    @font-face {
    	font-family: 'dearJoeItalic';
    	src: url('../fonts/DEARJI_.eot');
    	src: local('dearJoe Italic'), local('DearJoeItalic'), url('../fonts/DEARJI_.woff') format('woff'), url('../fonts/DEARJI_.ttf') format('truetype'), url('../fonts/DEARJI_.svg#DearJoeItalic') format('svg');
    }

    Is okay on everything except Firefox.

    You already knew that, right?

    Anway, carry on…

  22. Adam
    January 18th, 2010 at 07:59 #22

    Paul,

    I've got a suggestion for a simple way to check if font-face has worked and load up an alternative style sheet if it hasn't…

    - Put a div with an "M" in it using the embedded font
    - Check with of the div once loaded
    - As long as the new font has a different width M to arial, this should determine whether the font has loaded.
    - Then you can load a new stylesheet to make the failure of the font more graceful

    Your thoughts on this would be much appreciated.

    	function checkTheFont(){
    		var oElement = document.getElementById('font-test'), oWidth;
    		if( window.getComputedStyle ) {
    		  oWidth = window.getComputedStyle(oElement,null).width;
    		} else if( oElement.currentStyle ) {
    		  oWidth = oElement.currentStyle.width;
    		};
    		if (oWidth != "12px") {
    			if(document.createStyleSheet) {
    				document.createStyleSheet('nofonts.css');
    			} else {
    				var styles = "@import url('nofonts.css');";
    				var newSS=document.createElement('link');
    				newSS.rel='stylesheet';
    				newSS.href='data:text/css,'+escape(styles);
    				document.getElementsByTagName("head")[0].appendChild(newSS);
    			}
    		};
    	};
  23. January 24th, 2010 at 15:03 #23

    @Adam , that's the method this script basically uses. Just with a lot more robustness around it.

  24. Jose Garaza
    February 5th, 2010 at 13:58 #24

    I implement the code in a website that I'm working on and in IE6 return TRUE and in Safari and Chrome return FALSE unless i use the sniffer
    why is that? is more for learning purpose this question

    regards

  25. Jose Garaza
    February 8th, 2010 at 07:02 #25

    Ok i understand now, IE implement it since version 4.0

    regards

  26. February 12th, 2010 at 14:52 #26

    I would like to include some simple font selection on my site with forms. IE being the problem.
    Is @font-Face good enough to use for this and can 5 or 6 fonts be put into a selection list to choose and change them on the fly?
    I have not seen any examples of this yet.

    Thank You

  27. Carrie
    February 24th, 2010 at 17:33 #27

    I'm using the callback method, and am getting a false positive in Opera 9.63. Works great in all other browsers I've tested. Has anyone seen this?

  28. morgan
    March 5th, 2010 at 17:31 #28

    I'm a little bit confused with the amount of options here. There's this, and then there's Modernizr, and I also found what appears to be a modification of your script here. The one there actually does what I really want, which is to use @font-face if available, then degrade to Cufon. What do you recommend, though? It looks like Modernizr has a lot of extra stuff I might not use, but then again I might and it is awfully small. Does Modernizr make this script outdated?

  29. September 3rd, 2010 at 16:56 #29

    Hi, im trying to get the best out of both worlds and need Cufon as a fallback. Im not quite sure my understanding of Cufon or this script is correct. I am more of a Flash developer so Javascript is new. Anyways i tried the basics:

    //Using FontFace check to determine Cufon or @font-face
    isFontFaceSupprted.ready(function(isSupported){
    if (isSupported)
    {
    //Support
    var css = document.createElement('link');
    link.rel = 'stylesheet';
    link.type = 'text/css';
    link.href = 'css/fonts.css';
    document.body.appendChild(link);
    }
    else
    {
    //No-support
    Cufon.replace('h1', {textShadow: '0px 1px rgba(255,255,255,1)'});
    Cufon.replace('.intro-text', {textShadow: '0px 1px rgba(255,255,255,1)'});
    Cufon.now();
    }
    });

    No luck and im unsure of what im doing wrong..Any help would be appreciated, the script is great for this kind of stuff

  30. October 1st, 2010 at 13:38 #30

    Paul-
    This looks great, except what I'm dealing with slips through the cracks: a test of IE version is insufficient because a paranoid IE user can disabled font downloading under security settings. I don't know whether embedding the font inline in the css is considered "font download" or not, so it may still be necessary to verify that the font can be physically retrieved from off the webserver, in which case working around "the need to pull in an .eot" might be entirely acceptable..

    -Bronius

  31. jonathanrlively
    October 13th, 2010 at 14:53 #31

    @Adam
    Hey Adam, I've just spent the last 24 hours banging my head against the wall trying to fix this relative path issue in Firefox. If you or anyone else has a solution, you will be my new hero.

    The workaround I'm using is to just put a copy of the font file(s), a separate css file with the @font-face styling into the same directory as my html files, and then adding the font style into the html pages with an additional link to the css file.

    This works just fine but, I would rather find a way to fix the problem. Thanks all.

  32. October 13th, 2010 at 15:06 #32

    Bronius, there is no way to detect anything about those settings. The user will get prompted the second you try to use @font-face. :(

    Jonathan, you could also use javascript to determine what the absolute path should be.. and then write a new style tag with the @font-face declaration with the full URL.

  33. Luke Nickerson
    June 2nd, 2011 at 09:43 #33

    Typo above in Usage — isFontFaceSupprted missing the "o".

    Also, while using IE I had the function returning as true but the font not displaying. I believe another function is probably needed to actually check if a particular font is loaded; IE probably does not load standard font types. (?)

  34. July 6th, 2011 at 11:58 #34

    plzz tell me about the font being used here

  1. October 15th, 2009 at 13:17 | #1
  2. February 7th, 2010 at 05:03 | #2
  3. August 28th, 2010 at 01:21 | #3

For code blocks, use <pre lang="javascript">. css and html4strict are also accepted.

i left this space here for you to play. <3