老爷车IE8如何兼容图标字体

前言

首先这个标题再详细的说就是如何解决font-face在IE8下间歇性出现图标字体渲染失败的解决方案javascript

若是你还不知道什么是图标字体,能够先阅读:连接1连接2连接3css

先看在IE8下的问题:html

image

 

正常的应该是这样:java

image

能够看到因此图标都显示不了,最关键的是还显示出他自己的字符,这绝对是不能忍的,必须解决。jquery

 

问题的缘由究竟是什么?

这个页面是为了快速一览图标字体的页面,这两个截图都是在IE8下截图的,因此能够看到font-face不是不兼容IE8,而是间歇性的撂挑子(出问题),至于问题缘由:git

猜想:是由于字体并不阻塞页面显示,当第一次打开页面,字体文件没有缓存,且字体在页面打开后才载入进来,致使浏览器没有从新渲染页面中使用图标字体的字符,才致使此问题出现的github

 

一、搭建测试环境

首先要100%复现问题,肯定bug缘由。我是win8的开发机,用Oracle VM VirtualBox创建虚拟机,IE6 8 9各一台,如今用IE8测试web

image

 

开发环境是Visual Studio 2013,把项目跑起来后,开启Fiddler作虚拟机的代理服务器,也就是将Fiddler做为个人真实机的反向代理服务器,这样可让虚拟机链接个人真实机的localhost地址,来达到远程VS调试的功能。bootstrap

固然你能够直接把web文件发布到局域网内网IP,而后虚拟机访问,在本例中是能够的,可是那样VS是没法使用调试(debug)功能的。promise

image

如上图所示虚拟机成功链接真实的localhost,但目前是没问题的,咱们须要利用Fiddler来模拟网络问题。

 

 二、用Fiddler模拟网络问题

猜想是字体返回过慢,因此能够利用Fiddler的 BreakPoints ,即断点功能。

使用Fiddler-【Rules】-【Automatic Breakpoints】-【After Response】断点功能。

image

 

启用【After Response】即响应后断点,即响应已经发送至服务器,服务器也将资源返回给Fiddler,此时Fiddler等待其余资源都响应完成后,再返回给浏览器,以人为制造上述猜测的发生场景,过程以下图:

image

顺便一提,在本例中使用【Before Request】也是能够的,由于对于浏览器而言,使用请求前断点和响应后断点都是同样的。

 

接下来在虚拟机中的IE8按Ctrl+F5,强制全部资源均重新加载,在Fiddler中,把全部非字体资源文件都【Run to Completion】经过,转发给浏览器,最后再将字体转发给浏览器。

image

 

3、稳定复现

能够看到,问题又复现了:

image

若是此时关闭断点,再在虚拟机中清空缓存,并按Ctrl+F5 多少次,也没法复现此问题,只要使用Fiddler断点,就能够100%复现此问题。

问题找到了,就是后加载进来没法渲染,想办法强制触发渲染就能够了。

如何解决此问题?

 

解决方案1:加载完成后调整下浏览器大小

你们应该都知道,调整浏览器大小会形成网页重绘回流,会让页面几乎全部元素从新绘制。由于从新绘制样式了,因此天然也就能够了解决图标字体渲染失败的问题。

缺点天然不用说,这等于没解决,不过咱们能够利用重绘后图标生效的特性来让强制令其页面回流重绘。

关于不知道什么是回流与重绘的同窗能够参考:连接1连接2

 

解决方案2:强制回流

既然咱们要让全部图标字体都生效,那么最好的办法是让页面发生大面积回流,以触发整页从新渲染。那么咱们就须要先知道有哪些操做能够致使回流:

如下操做会触发回流:

一、调整窗口大小

二、改变字体

三、增长或者移除样式表

四、内容变化,好比用户在input框中输入文字

五、激活 CSS 伪类,好比 :hover (IE 中为兄弟结点伪类的激活

六、操做 class 属性

七、脚本操做 DOM

八、计算 offsetWidth 和 offsetHeight 属性

九、设置 style 属性的值

十、其余会致使回流的操做

因此就有了如下失败的尝试:

给body顶部插入元素,设定body的宽度,设定绝对定位再设置回来,强制修改font-face的字体再改回来等等,最终解决是没成功,若是各位有什么好办法欢迎留言。

 

解决方案3:重设font-face的伪类内容

最终经过设置 !important 来覆盖全部font-face的css,再从新应用就能够实现了。

代码:

<style>
    html.fix-ie-font-face :before,
    html.fix-ie-font-face :after {
        content: none !important;
    }
</style>
<script>
    //重设伪类,使字体强制生效
    !(function redrawFontFace() {
        if ($.support.leadingWhitespace) return;
        $(window).one("load", function() {
            console.log("onload!!!!!!!!!!!");
            $('html').addClass('fix-ie-font-face');
            setTimeout(function() {
                $('html').removeClass('fix-ie-font-face');
            }, 10);
        });
    }());
</script>

 

原理就是先让全部图标字体失效,再让他们生效,就能够了。

须要注意的一点是:必须注册为 window 的 onload 事件。

最经常使用的$.ready()是不行的,他的本质是 DOMContentLoaded ,他会在DOM加载结束后就触发,咱们须要在图标字体文件加载后再执行,由于没有字体加载后的load事件(若是有请必定告诉我),因此必需要在整页全部资源都加载完成后再触发本函数。

顺便附上jquery中的 $.ready 实现方法源码:

//jquery-1.9.1.js #885
jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {

        readyList = jQuery.Deferred();

        // Catch cases where $(document).ready() is called after the browser event has already occurred.
        // we once tried to use readyState "interactive" here, but it caused issues like the one
        // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
        if ( document.readyState === "complete" ) {
            // Handle it asynchronously to allow scripts the opportunity to delay ready
            setTimeout( jQuery.ready );

        // Standards-based browsers support DOMContentLoaded
        } else if ( document.addEventListener ) {
            // Use the handy event callback
            document.addEventListener( "DOMContentLoaded", completed, false );

            // A fallback to window.onload, that will always work
            window.addEventListener( "load", completed, false );

        // If IE event model is used
        } else {
            // Ensure firing before onload, maybe late but safe also for iframes
            document.attachEvent( "onreadystatechange", completed );

            // A fallback to window.onload, that will always work
            window.attachEvent( "onload", completed );

            // If IE and not a frame
            // continually check to see if the document is ready
            var top = false;

            try {
                top = window.frameElement == null && document.documentElement;
            } catch(e) {}

            if ( top && top.doScroll ) {
                (function doScrollCheck() {
                    if ( !jQuery.isReady ) {

                        try {
                            // Use the trick by Diego Perini
                            // http://javascript.nwbox.com/IEContentLoaded/
                            top.doScroll("left");
                        } catch(e) {
                            return setTimeout( doScrollCheck, 50 );
                        }

                        // detach all dom ready events
                        detach();

                        // and execute any waiting functions
                        jQuery.ready();
                    }
                })();
            }
        }
    }
    return readyList.promise( obj );
};
$.ready的源码

 

 

其余问题

一、IE8下图标字体很是有锯齿感怎么解决?如图

image

解决方案:作一张1*1大小的透明PNG图,而后给全部的图标字体的类样式增长IE特有的 filter 属性,以下:

filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=images/IEfix.png, sizingMethod=crop);
zoom: 1;

增长滤镜后效果:

image

图标看上去还算说得过去,至于文字的锯齿,不是本文探讨的范围内,辣个要去电脑中设置了。

缺点就是会下降页面打开速度,增长页面CPU占用量,会让页面变卡,固然前提是你页面使用了太多图标字体。

 

二、待补充…

 

代码下载

本文代码已托管至Github:

https://github.com/xxcanghai/cnblogsFiles/tree/master/fix-IE-bootstrap-font-face

 

扩展阅读

 

一、页面重绘和回流以及优化

二、回流与重绘:CSS性能让JavaScript变慢?

三、IE8 CSS @font-face fonts only working for :before content on over and sometimes on refresh/hard refresh

四、再不知道字体图标就落伍啦!

五、Font Awesome

(完)

原文地址-http://www.cnblogs.com/xxcanghai/p/5000984.html

相关文章
相关标签/搜索