IE8 web字体iframe bug变通办法

时间:2011-10-14 13:05:27

标签: css iframe internet-explorer-8 rendering font-face

This blog post(那里有点讨厌的页面)(顺便说一下,这不是我的博客)描述了我昨天在Internet Explorer 8中遇到的一个奇怪的错误。该错误涉及.EOT网络字体和<iframe>元素。

我没有广泛研究错误的确切触发器,但基本上情况是使用网页字体的网页将内容加载到<iframe>,以便框架使用网络字体被浏览器变为“污损”。使用Web字体呈现的先前正常文本突然转变为看起来很糟糕的Arial或其他类似的东西。有时它会翻转,只会在鼠标移动等随机用户交互中再次降级。

该博客文章有一个例子。澄清一下,它是包含在内的页面,而不是<iframe>中的页面(至少,就我的经验而言,情况就是如此)。

是否有人找到了比该博客中建议的更好的解决方法,即强制从<link>声明的来源“重新加载”CSS @font-face元素? (我可以做到这一点,但这只是一个轻微的痛苦,加上它会迫使我将我的字体设置移出我的文档<head>,如果我记得这是一个性能问题;我将不得不四处寻找再次找到那个花絮。)

编辑 - 更新

确定here's a test 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>

框架页面具有相同的@font-face和虚拟消息。

这个问题似乎与使用加载的字体有关,其中包含多个备用字体的列表。我(没有充分理由)在我的“font-family”值中抛出了几个类似的更常见的字体。当我把它们放回去时:

 .title { font-family: bold-display, sans-serif; }
然后问题消失了(或者至少它似乎已经消失了。)

感谢那些帮助过的人。致@albert,添加一个总结你尝试过的答案的答案,我会向你投票: - )

9 个答案:

答案 0 :(得分:25)

因此,以下内容没有性能影响(只要CSS的大小合理),您可以将<link>标记保留在<head>中,它没有问题,但你仍然基本上“重新加载”你的<link>元素(虽然你没有通过重置他们的网址这样做)。

删除<iframe>元素后,只需执行以下操作:

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

重新加载是我真正想到的所有工作,因为它似乎是从<iframe>中的垃圾收集中删除它。设置test page,显然只适用于IE 8。

注意:我原本无法使用Google网络字体重新解决此问题,并且必须专门下载.eot字体才能使用此字体。所以你的工作可能首先使用WOFF字体,并且只在必要时加载EOT。

不确定这是否是您所寻找的,但如果不是,请澄清,我会根据需要进行编辑。

更新1:原因

所以,我已经缩小了问题的原因。如果发生以下情况,我只能复制(这是一个令人讨厌的人)。

  • <iframe>包含在父元素
  • 更改了父元素的类
  • 班级不会更改正在应用的元素的display(或者实际上,如果它不会更改<iframe>元素上的整体显示)

而且,据我所知,是的,它必须是班级名称。在元素的id上给出相同的步骤,我无法重现。认真。这个是令人讨厌的。我会继续挖掘一下。

更新2:次要原因

如果<iframe>在浏览器窗口中没有完全显示,它将不会在<iframe>窗口中加载字体,并且只要必须重新绘制主窗口,就会卸载主窗口的字体页面(最值得注意的是调整大小时)。这是一个粗糙的错误。

更新3:应该是什么解决方案

而不是使用display: none;,将元素的高度和宽度设置为0pxoverflow: hidden;,您将获得与显示无效相同的效果,但它不会将其从DOM中删除,因此不会重新绘制页面并使用您的字体。我之前的test page已经更新,因此您可以看到对以前的错误的影响。

答案 1 :(得分:2)

如果您刚刚通过fontsquirrel.com生成跨浏览器@font-face语法,我认为您甚至不会遇到问题。你想嵌入:

@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 */
}

如果发现语法失败,也可以使用webfont loader脚本。我没有将功能与上面回答的代码进行比较(我确信它有效),this is the js typekit和googlefonts用于加载他们的字体。

答案 2 :(得分:2)

我偶然发现了这个q&amp; a研究一个非常相似的情况,除了没有任何参与的iframe。所有这一切都是使用谷歌网络字体和许多浮动的divs导致IE8重新加载后以不同的方式呈现文本。读过这个

  

问题似乎与使用带有多个备用字体列表的已加载字体有关。

我将我的css中的font-stack更改为只有一个替代方案,并且bug消失了。

非常感谢你指出我正确的方向!

答案 3 :(得分:2)

我最终使用的解决方案是

@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;
}

然后只引用iframe css中的Iframe字体系列。它有点额外的css,但我认为如果你只使用几种字体,它必须重新加载css更好。

答案 4 :(得分:1)

其他建议的解决方案都没有为我们工作,所以我们最终只需要隐藏整个页面,直到页面加载完毕。我们用以下代码完成了这个:

<!--[if lte IE 8]>
    <style type="text/css">
        html {
            visibility: hidden;
        }
    </style>
    <script type="text/javascript">
        $(window).load(function() {
            $('html').css('visibility', 'visible');
        });
    </script>
<![endif]-->

答案 5 :(得分:1)

IE&lt; 9处理字体的src属性的方式有一个错误。

根据https://github.com/stubbornella/csslint/wiki/Bulletproof-font-face,你可以通过简单地在第一个字体网址后面添加一个问号来避免它,并欺骗浏览器解释网址的方式。对我来说就像一个魅力。

答案 6 :(得分:1)

我们遇到的问题似乎是当无法加载具有相同名称的iframe时(在我们的例子中是404),IE会(有时)卸载主页面上的字体。我们的解决方案是重命名iframed页面上的字体(如果由于某种原因无法加载字体而无法加载)并确保正常加载它。

答案 7 :(得分:1)

我的解决方案是为IE8设置排版的一种可能性。例如:

general.css

@font-face {
  font-family: 'patua-one'; /PatuaOneRegular';/
  src: url('../fonts/PatuaOne-Regular-webfont.eot');
  src: url('../fonts/PatuaOne-Regular-webfont.eot?#iefix') format('embedded-opentype'),
       url('../fonts/PatuaOne-Regular-webfont.woff') format('woff'),
       url('../fonts/PatuaOne-Regular-webfont.ttf') format('truetype'),
       url('../fonts/PatuaOne-Regular-webfont.svg#PatuaOneRegular') format('svg');
  font-weight: normal;
  font-style: normal;
}

body {
    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
}

h1,h2,h3,h4,h5,h6 {
    font-family: patua-one,Arial,Helvetica Neue,Helvetica,sans-serif;
}

<!--[if IE 8]>
    <link rel="stylesheet" type="text/css" href="ie8.css">
<![endif]-->

ie8.css

body {
    font-family: Arial;
}

h1,h2,h3,h4,h5,h6 {
    font-family: patua-one;
}

答案 8 :(得分:1)

我遇到了类似的问题,但它是一个简单的框架集,而不是动态的iframe。重复ktash的答案,这会将黑客集中到顶层框架中,而不会影响可能加载到框架集周围的所有页面。

条件块将覆盖IE8的onload处理程序。

偶尔会有FOUC,但至少情况会自行纠正,而不是要求用户四处走动。

<html>
<head>
<script>
function markFrameLoaded() { 
    // noop for the well behaved browsers of the world
}
</script>
<!--[if IE 8]>
<script>
function markFrameLoaded() {
    var frameCount = window.frames.length;
    for ( var f = 0 ; f < frameCount ; f++ ) {
        var styleCount = window.frames[f].document.styleSheets.length;
        for ( var s = 0 ; s < styleCount ; s++ ) {
            var sheet = window.frames[f].document.styleSheets[s];
            sheet.disabled = true;
            sheet.disabled = false;
        }
    }
}
</script> 
<![endif]-->
</head>
<frameset rows="*,*">
<frame src="top.html" onload="markFrameLoaded()">
<frame src="bottom.html" onload="markFrameLoaded()">
</frameset>
</html>