IE8 веб-шрифт iframe ошибка обходные пути

этот блог (немного раздражает страница там) (и это не мой блог, кстати) описывает странную ошибку, с которой я столкнулся вчера только в Internet Explorer 8. Ошибка связана .Веб-шрифты EOT и <iframe> элементы.

Я не подробно исследовал точный триггер для ошибки, но это в основном случай, когда страница с использованием веб-шрифта, который загружает контент в <iframe> такой, что кадр и использует веб-шрифт становится "испорченным" броузер. Ранее-OK текст, отображаемый с помощью веб-шрифта, внезапно переходит на ужасно выглядящий Arial или что-то еще, вроде-самостоятельно. Иногда он переворачивается назад, только чтобы снова деградировать при случайных взаимодействиях пользователей, таких как движения мыши.

в этом блоге есть пример. Чтобы уточнить, это содержащая страница, которая запутывается, а не страница в <iframe> (по крайней мере, до сих пор в моем опыте).

кто-нибудь нашел лучшее решение, чем то, что предлагается в этом блоге, который должен заставить" перезагрузить " CSS <link> элемент, откуда @font-face заявления? (Я мог бы это сделать, но это была бы небольшая боль, плюс это заставило бы меня переместить настройку шрифта из моего документа <head> что, если я припоминаю, является проблемой производительности; мне придется копаться и снова найти этот лакомый кусочек.)

редактировать - обновление

OK вот тестовая страница. Вот основной (контейнер) страница:

<!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(/bshowingb/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 и фиктивное сообщение.

проблема, похоже, имеет какое-то отношение к используя загруженные шрифты со списком из нескольких альтернативных шрифтов. Я (без веской причины) бросил пару похожих более распространенных шрифтов в моих значениях "шрифт-семья". Когда я бросил их обратно:

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

затем проблема ушла (или, по крайней мере, кажется, что она ушла так дальний.)

спасибо тем, кто помог. В @albert добавьте ответ, суммирующий то, что вы пробовали, и я вас поддержу :-)

9 ответов


так, нет работы со следующим (пока ваш CSS имеет разумный размер), вы можете оставить <link> tag in <head>, и он работает без проблем, но вы все еще в основном "перезагружаете" свой <link> элементы (хотя вы не делаете этого, сбрасывая их url-адрес).

об отстранении <iframe> элемент, просто сделайте следующее:

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

перезагрузка-это все, что я могу думать о работе, так как это кажется удаление его в сборке мусора из <iframe>. Настройте тестовая страница это, очевидно, работает только для IE 8.

Примечание: изначально я был не в состоянии reprodcue эту проблему с помощью веб-шрифтов Google, и пришлось специально скачать .eot шрифт для использования для этого. Поэтому ваша работа вокруг, возможно, сначала использовать шрифты WOFF и загружать EOT только при необходимости.

не совсем уверен, что это то, что вы искали, но если это не так, пожалуйста уточнить и я буду редактировать по мере необходимости.

обновление 1: причина

Итак, я сузил причину проблемы. Я могу воспроизводить только в том случае, если происходит следующее (И это неприятный человек).

  • и <iframe> содержится в родительском элементе
  • класс родительского элемента изменен
  • класс не изменить display элемента, к которому он применяется (или действительно, если он не изменяет общий дисплей на <iframe> элемент)

и, из того, что я могу сказать, Да, это должно быть имя класса. Я не смог воспроизвести те же шаги на id элемента. Серьезно. Это отвратительно. Я продолжу копать.

Обновление 2: Вторичная Причина

если <iframe> не полностью в окне браузера при рисовании, он не будет загружать шрифт в <iframe> окно, и выгрузит шрифт для главного окна всякий раз, когда ему придется перерисовывать страницу (особенно, когда она изменяется). Это корявый Жук.

обновление 3: Каким должно быть решение

вместо display: none;, установить высоту и ширину элемента 0px и overflow: hidden;, и вы получите тот же эффект, что и display none, но он не удалит его из DOM, тем самым не перерисовывая страницу и не принимая ваш шрифт. Мой тестовая страница раньше был обновлен, поэтому вы можете увидеть эффект от того, что раньше было ошибкой.


Если вы только что создали кросс-браузер @font-face синтаксис через fontsquirrel.com я не думаю, что у тебя будут проблемы. вы хотите быть встраивание:

@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, если обнаружите, что синтаксис не работает. Я не сравнивал функциональность с кодом, на который ответил выше (я уверен, что он работает),это js typekit и googlefonts используют для загрузки своих шрифтов.


Я столкнулся с этим q&A, исследуя очень похожую ситуацию, за исключением того, что iframe вообще не участвует. Все, что потребовалось, это использовать веб-шрифт google и много плавающих divs, чтобы заставить IE8 отображать текст по-разному после перезагрузки. Прочитав это

проблема, похоже, связана с использованием загруженных шрифтов со списком из нескольких альтернативных шрифтов.

Я изменил стек шрифтов в моем css только на один альтернатива, и жучок исчез.

большое спасибо, что указал мне в правильном направлении!


решение, которое я использовал, было

@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, если вы используете только несколько шрифтов.


ни одно из других предложенных решений не работало для нас, поэтому нам пришлось просто держать всю страницу скрытой, пока страница не была загружена. Мы сделали это со следующим фрагментом кода:

<!--[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]-->

IE

согласно https://github.com/stubbornella/csslint/wiki/Bulletproof-font-face, Вы можете избежать этого, просто добавив вопросительный знак после первого url шрифта и обмануть способ, которым браузер интерпретирует url. Сработало как по волшебству.


проблема, с которой мы столкнулись, заключалась в том, что, когда iframe с тем же именем не удалось загрузить (404 в нашем случае), IE (иногда) выгружал шрифт на главной странице. Наше решение состояло в том, чтобы переименовать шрифт на странице iframed (в случае, если шрифт не может быть загружен по какой-то причине вне нашего контроля) и убедиться, что он правильно загружен нормально.


моим решением было установить только одну возможность типографики для IE8. Пример:

общие.в 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;
}

У меня была аналогичная проблема, но она была с простым набором фреймов, а не с динамическими iframes. С ответом Из ktash, это централизует взлом в рамку верхнего уровня, не влияя на все страницы, которые могут загружаться вокруг набора фреймов.

условный блок переопределит обработчик onload только для IE8.

есть еще 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>