Методы обхода ошибки встроенного шрифта в IE8 - PullRequest
29 голосов
/ 14 октября 2011

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

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

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

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

edit - update

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(/\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 ]

25 голосов
/ 25 октября 2011

Таким образом, при следующем ( при условии, что ваш CSS разумного размера ) нет никакого снижения производительности, вы можете оставить тег <link> в <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.

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

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

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

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

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

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

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

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

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

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

2 голосов
/ 30 апреля 2013

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

@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 в iframe cssЭто немного больше CSS, но я думаю, что лучше перезагрузить CSS, если вы используете только несколько шрифтов.

2 голосов
/ 25 февраля 2012

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

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

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

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

2 голосов
/ 26 октября 2011

Если вы только что сгенерировали кросс-браузерный синтаксис @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, которые используются для загрузки их шрифтов.

1 голос
/ 11 сентября 2013

У меня была похожая проблема, но это было с простым набором кадров, а не с динамическими фреймами.Опираясь на ответ от ktash , это централизует взлом в фрейм верхнего уровня, не затрагивая все страницы, которые могут загружаться вокруг frameset.только 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>
1 голос
/ 18 июня 2013

Моим решением было установить только одну возможность типографики для 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;
}
1 голос
/ 17 апреля 2013

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

1 голос
/ 17 апреля 2013

IE <9 содержит ошибку в способе обработки атрибута src шрифта.</p>

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

1 голос
/ 03 мая 2012

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

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