saber酱的抱枕

生于忧患,死于安乐

11/19
12:16
学习

IE8的兼容性问题

浏览器份额

IE8无疑是个坑爹货,但XP上的IE最高只到IE8。根据百度统计流量研究院的数据,目前IE8在国内仍然占有15%的份额(不过这个图上的数据看得我怀疑人生)。

IE8的兼容性也是一个大坑。最近做一个网站,想要兼容IE8,于是翻出了许多遇到过和没遇到过的坑,略微整理一下。

css部分

1.opaticy

IE8不支持css的opaticy(透明度)属性,需要使用IE的私有滤镜来实现。示例:

opacity:0.7;	/*现代浏览器*/
filter:alpha(opacity=70);	/*IE8及以下*/

也可以视情况考虑针对IE8,用display的block、none来取代opcity的1、0。

2.border-radius

IE8不支持css的border-radius(圆角)属性,这个可以使用ie-css3.htc文件解决(但不完美,还可能出现预料之外的问题)。我现在没去处理它。

3.rgba颜色

rgba颜色格式通常用于设置一个半透明的背景色。但IE8不支持,而且也不认这个属性。怎么处理呢?

第一种方式是不处理。就是在IE8里不透明,在其他浏览器里透明。

background: rgb(0,0,0);		/*IE8可以识别这个*/
background: rgba(0,0,0,.7);	/*现代浏览器则会使用这一条覆盖上一条*/

第二种方法,是使用IE的滤镜来解决。如:

filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#7f000000,endColorstr=#7f000000); /*使用半透明渐变来实现半透明背景*/

这个也有点麻烦。调整透明度的话,需要调整最后两个颜色值前面的7f。7f后面的6位貌似是颜色值的16进制。参考此处或自顶搜索。

第三种方法,就是不使用背景色,直接使用半透明png图片做背景。

4.background-size: 100% 100%;

IE8不支持background-size属性,解决办法也是使用滤镜:

filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/background.jpg',sizingMethod='scale');/*兼容ie8以下*/

sizingMethod='scale'就是让背景图片始终拉伸到和容器一样大小,在效果上和background-size: 100% 100%;一致。

5.max-width:100%的bug

IE8支持max-width,但有时候会出现bug,导致图片不显示。此时通过IE8的开发人员工具看到页面布局里图片宽度为0。

如下的代码,在IE8里会导致图片不显示:

<div id="float">
    <img src="img.jpg" alt="">
</div>
<style>
	#float{float: left;}
	#float img{width: 100%;max-width: 100%;height: 100%;} /*让图片自适应容器宽高*/
</style>

当图片的父元素是浮动元素,且图片同时有值不为auto的width和max-width:100%两个属性,就会导致图片不显示。

解决办法:
需要给父元素——浮动元素指定宽度。如px或百分比。

其实昨天我出现图片不显示的时候,直接父元素并没有浮动。最后我也不记得怎么解决的了。

5.不支持css媒体查询

IE8不支持css媒体查询,如下样式在IE8中无效:

@media screen and (min-width: 640px){
    .topnav{display: none;}
}

解决办法是在引入外部css文件之后加载Respond.js来解决。

示例:

<!--[if IE]>
<script type="text/javascript" src="js/respond.js"></script>
<![endif]-->

Respond.js可以让IE6-IE8支持css媒体查询。
参考来源

6.不支持html5标签

IE8及以下浏览器并不支持html5的新标签,如header、nav、section、article、footer等。我们可以用Google的html5shiv这个js来解决。

我们需要做的是首先引入html5shiv,如下(下面代码里用的是国内的cdn):

<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<![endif]-->

之后,还要在css文件里对html5的这些新标签初始化:

/*html5*/
article,aside,dialog,footer,header,section,footer,nav,figure,menu{display:block} 

这样,我们就可以在IE8里使用这些标签了。

7.不支持css3动画

因为我只用了一个过渡属性(transition),所以我没处理这个问题。

想要解决的话,简单的动画效果可以考虑使用JavaScript来实现。必须用css3来做的可以参考下csssandpaper.js(我没试过这个)。

8.伪元素的写法(:和::)

对于伪元素如::after和::before这样的,其实使用双冒号更符合新规范,这是为了将伪元素(双冒号)和伪类(单冒号)区分开来。

但是IE8只支持单冒号,所幸现代浏览器同时兼容单冒号和双冒号,所以我们要兼容IE8的话写成单冒号就行了。

9.针对IE8做css hack

1.用媒体查询来做。因为IE8不支持媒体查询(上面引入了额外的js使其支持是特例),那么我们可以把要做hack的css先在媒体查询外写一份,这一份IE8可以识别。要让其他浏览器支持的部分写在媒体查询内,就可以覆盖先前为IE8做的定义。如:

/*这一句兼容IE8*/
img{display: none;}
/*下面针对其他浏览器生效*/
@media screen and (min-width:0px){
	img{display: inline;opacity: 0;}
}

在现代浏览器里,通过透明度变化让一个元素隐藏,在IE8里则直接display: none。

至于在css后面写\9或者\0之类的,不仅IE8可以识别,IE9-10都可以识别,所以不好用了。

2.如果上面的办法太麻烦或者不适用,也可以尝试用JavaScript来识别IE8,然后输出css样式。

参考:《JS代码判断IE6,IE7,IE8,IE9的函数代码》

10.IE8下改变select高度,文字不再垂直居中

如果我们通过css设置height加高了select下拉框的高度,那么即使设置了同样的line-height,IE8里文字还是不会垂直居中,而是靠近底边。怎么办呢?增加上下padding来挤。

如:

select{height: 30px;line-height: 30px;padding:4px 0;}

什么意思呢?这里有个关键点,select是比较特殊的,增加padding并不会增加高度,而是会挤压高度。

假设IE8里select的默认高度是22px,我们手动设置的高是30px,相差8px。那么把差值8除以2得到4,去设置paddingTop和paddingBottom的值,就ok了。

这样处理后相当于select的高度其实是22px,默认高度。这样IE8里看起来就居中了,在其他浏览器里也没问题。


javaScript部分

1.attachEvent和addEventListener

IE8及以下绑定事件需要使用attachEvent方法,与现代浏览器区别如下:

if (!!window.attachEvent) {
    document.querySelector("#a").attachEvent("onclick",fun);
}else{
    document.querySelector("#a").addEventListener("click",fun,false);
}

解决这个兼容性的代码如下:

function addEvent(obj, ev, fn) {
	if (obj.attachEvent) {   //针对IE浏览器
		obj.attachEvent('on' + ev, fn)
	} else {   //针对FF与chrome
		obj.addEventListener(ev, fn, false)
	}
}

但如果添加的函数中用到了this,那么在IE低版本里会出错,this会是window。所以用到this的话建议先在函数里保存成一个变量使用,之后再添加到事件上。如下:

addEvent(oBtn, 'click', function(ev) {
	var oEvent = ev || event;
	var that = oEvent.srcElement || oEvent.target;
	alert(that);
})

2.currentStyle和getComputedStyle

使用javaScript获取元素计算后的样式,在IE8中需要使用currentStyle。示例:

<div id="a">xxxxxx</div>
<style>
	#a{color: #0c0;}
</style>
<script>
	var a=document.querySelector("#a");
	if (!!a.currentStyle) {
		alert(a.currentStyle["color"]);
	}else{
		alert(getComputedStyle(a,false)["color"])
	}
</script>

IE8返回的颜色值是16进制格式,现代浏览器返回的是rgb格式。

也可以封装一个方法:

//获取元素计算后的样式
function getStyle(obj, name) {
	if (obj.currentStyle) {
		return obj.currentStyle[name];
	} else {
		return getComputedStyle(obj, false)[name];
	}
}

但是IE8的样式默认值还有一个坑,如果一个元素没有指定margin,那么它的四个margin值默认不是0,而是auto。

奇了,假如我给一个元素固定宽度,但不指定margin。那么IE8的marginLeft和marginRight默认都是auto,这个元素不是应该居中吗?实际上并不会居中。但默认值就是auto,真是脑残设计。对此兼容如下:

var a = document.querySelector("#a"),
	ml = getStyle(a, "marginLeft"),
	mr = getStyle(a, "marginRight");
ml === "auto" ? 0 : ml;
mr === "auto" ? 0 : mr;

如果获取的是auto则转化为0。

3.不支持getElementsByClassName

如果只考虑IE8的话,可以使用querySelector()方法和querySelectorAll()方法来选择DOM元素。不使用getElementsByClassName就不会有这个问题了。如果一定要使用getElementsByClassName,可以用以下代码在低版本IE里实现一个getElementsByClassName方法:

if (!document.getElementsByClassName) {
    document.getElementsByClassName = function(className, element) {
        var children = (element || document).getElementsByTagName('*');
        var elements = new Array();
        for (var i = 0; i < children.length; i++) {
            var child = children[i];
            var classNames = child.className.split(' ');
            for (var j = 0; j < classNames.length; j++) {
                if (classNames[j] == className) {
                    elements.push(child);
                    break;
                }
            }
        }
        return elements;
    };
}

先这么多吧,再遇到新的问题的话再说。

IE8的兼容性问题

      1. locationiskey
        Google Chrome 54Google Chrome 54Windows 7Windows 7

        和手游一样,渠道为王。只是渠道都是他们自己掌控。

        普通人才不会觉得这些垃圾,只会有“垃圾浏览器上不了XX网站还不如用360qq”
        全家桶也只会觉得“啊好方便”

        回复