IE8 web font iframe bug workarounds

10,441

Solution 1

So, there is no performance hit with the following (as long as your CSS is reasonably sized), you get to leave the <link> tag in <head>, and it works without issue, but you are still basically 'reloading' your <link> elements (though you are not doing so by resetting their url).

On the removal of the <iframe> element, simply do the following:

var sheets = document.styleSheets;
for(var s = 0, slen = sheets.length; s < slen; s++) {
    sheets[s].disabled = true;
    sheets[s].disabled = false;
}

Reloading is all I can really think of as working since it seems to be removing it in garbage collection from the <iframe>. Set up a test page that obviously only works for IE 8.

Of Note: I was originally unable to reprodcue this issue using Google web fonts, and had to specifically download a .eot font for use for this. So your work around maybe to use WOFF fonts first, and only load EOT if necessary.

Not exactly sure if this is what you were looking for, but if it's not, please clarify and I'll edit as necessary.

Update 1: The cause

So, I've narrowed down the cause of the issue. I am only able to reproduce if the following occurs (and this is a nasty one folks).

  • And <iframe> is contained within a parent element
  • The parent element's class is changed
  • The class does not change the display of the element it is being applied to (or really, if it does not change the overall display on the <iframe> element)

And, from what I can tell, yes, it has to be the class name. I was unable to reproduce given the same steps on the id of an element. Seriously. This one is a nasty one. I'll keep digging a bit.

Update 2: A Secondary Cause

If the <iframe> is not fully in the browser window on draw, it will not load the font within the <iframe> window, and will unload the font for the main window whenever it has to redraw the page (most notably when it is resized). This is a gnarly bug.

Update 3: What should be a solution

Instead of using display: none;, set the height and the width of the element to be 0px and the overflow: hidden;, and you'll get the same effect as display none, but it will not remove it from the DOM, thereby not redrawing the page and taking your font. My test page from before has been updated, so you can see the effect on what used to be the bug.

Solution 2

The solution I ended up using was

@font-face {
    font-family: 'NewsGothicFSMedium';
    src: url('NewsGothic-Medium-webfont.eot');
    src: url('NewsGothic-Medium-webfont.eot?#iefix')  format('embedded-opentype'),
         url('NewsGothic-Medium-webfont.woff') format('woff'),
         url('NewsGothic-Medium-webfont.ttf') format('truetype'),
         url('NewsGothic-Medium-webfont.svg#webfont') format('svg');
    font-weight: normal;
    font-style: normal;
}

@font-face {
    font-family: 'NewsGothicFSMediumIframe';
    src: url('NewsGothic-Medium-webfont.eot');
    src: url('NewsGothic-Medium-webfont.eot?#iefix')  format('embedded-opentype'),
         url('NewsGothic-Medium-webfont.woff') format('woff'),
         url('NewsGothic-Medium-webfont.ttf') format('truetype'),
         url('NewsGothic-Medium-webfont.svg#webfont') format('svg');
    font-weight: normal;
    font-style: normal;
}

Then just reference the Iframe font-family within the iframe css. Its a little extra css but I think its better then having to reload css if you are only using a few fonts.

Solution 3

I came across this q&a while researching a very similar situation with the exception of no iframe whatsoever being involved. All it took was using a google web font and a lot of floated divs to cause IE8 to render the text differently after reload. Having read this

The problem appears to have something to do with using the loaded fonts with a list of more than one alternate font.

I changed the font-stack in my css to only a single alternative, and the bug went away.

Thanks a lot for pointing me in the right direction!

Solution 4

If you just generated cross-browser @font-face syntax via fontsquirrel.com, I don't think you'd even have an issue. you want to be embedding:

@font-face{
    font-family: 'DejaVuSansBook';
    src: url('DejaVuSans-webfont.eot'); /* ie9 compat mode */
    src: url('DejaVuSans-webfont.eot?#iefix') format('eot'),  /* ie 6-7-8 */
         url('DejaVuSans-webfont.woff') format('woff'), /* modern browsers */
         url('DejaVuSans-webfont.ttf') format('truetype'), /* Safari, Android, iOS */
         url('DejaVuSans-webfont.svg#webfontLXhJZR1n') format('svg'); /* Legacy iOS */
}

you could also use the webfont loader script if you find the syntax failing. I didn't compare functionality to the code answered above (I'm sure it works), this is the js typekit and googlefonts use to load their fonts.

Solution 5

IE < 9 has a bug in the way it handles the src attribute of the font.

According to https://github.com/stubbornella/csslint/wiki/Bulletproof-font-face , you can avoid it by simply adding a questionmark after the first font url and trick the way the browser interprets the url. Worked like a charm for me.

Share:
10,441
Pointy
Author by

Pointy

Software developer, front-end and various other ends.

Updated on June 08, 2022

Comments

  • Pointy
    Pointy almost 2 years

    This blog post (slightly annoying page there) (and that's not my blog by the way) describes a bizarre bug I ran into yesterday in Internet Explorer 8 only. The bug involves .EOT web fonts and <iframe> elements.

    I haven't extensively researched the exact trigger for the bug, but it's basically the case that a page using a web font that loads content into an <iframe> such that the frame also uses a web font becomes "defaced" by the browser. The previously-OK text rendered with the web font suddenly shifts to awful-looking Arial or something else, sort-of on its own. Sometimes it flips back, only to degrade again on random user interactions like mouse moves.

    That blog post has an example. To clarify, it's the containing page that gets messed up, not the page in the <iframe> (at least, that's the case so far in my experience).

    Has anybody found a better workaround than what's suggested in that blog, which is to force a "reload" of the CSS <link> element from whence the @font-face declarations come? (I could do that but it'd be a minor pain, plus it would force me to move my font setup out of my document <head> which if I recall is a performance issue; I'll have to scrounge around and find that tidbit again.)

    editupdate

    OK here's a test page. Here's the main (container) page:

    <!DOCTYPE html>
    <html>
      <head>
        <style id='font_style'>
          @font-face {
            font-family: 'bold-display';
            src: url('DejaVuSans-Bold.eot');
          }
        </style>
        <style>
          .fancy { font-family: bold-display, "franklin gothic medium", "verdana", sans-serif; font-size: 32px; }
          iframe { width: 500px; height: 200px; }
          #floater {
            position: absolute;
            top: 100px; left: 100px;
            display: none;
          }
          #floater.showing {
            display: block;
          }
        </style>
        <script>
          function load() {
            var frame = document.createElement('iframe'),
              floater = document.getElementById('floater'),
              target = document.getElementById('target');
    
            frame.src = 'frame.html';
            target.appendChild(frame);
            floater.className += 'showing';
          }
          function unload() {
            var floater = document.getElementById('floater'),
              target = document.getElementById('target');
            target.innerHTML = '';
            floater.className = floater.className.replace(/\bshowing\b/g, '');
          }
        </script>
      </head>
      <body>
        <div class='fancy'>Hello World</div>
        <button type='button' onclick='load()'>Click Me</button>
        <div id='floater'>
          <div id='target'></div>
          <button type='button' onclick='unload()'>Close</button>
      </body>
    </html>
    

    The frame page has the same @font-face and a dummy message.

    The problem appears to have something to do with using the loaded fonts with a list of more than one alternate font. I (for no good reason) had tossed in a couple of similar more-common fonts in my "font-family" values. When I dropped them back to:

     .title { font-family: bold-display, sans-serif; }
    

    then the problem went away (or at least it seems to have gone away so far).

    Thanks to those who've helped out. To @albert, add an answer summarizing what you tried and I'll upvote you :-)