Fork me on GitHub
秋染蒹葭

浏览器的兼容性问题解决方案

所谓浏览器兼容性问题指的是不同的浏览器对同一段代码不同的解析,造成页面显示效果不统一的情况。而我们想要的是无论用户使用什么浏览器打开我们的网站,都应该显示的是统一的效果,兼容性问题是前端开发必须要考虑的问题。

属性

input的type属性

h5提供了很多类型的input,使用这些input有很多好处,浏览器可以通过这些type调用不同的键盘(iphone上),对于ie8,ie9对于某些不识别的type会识别成text,比如type=’email’。

vw属性

IE8不支持,啦啦啦

float

ie6,ie7不兼容,但是还是有问题

overflow

overflow:hidden 的 BFC 特性从 IE7 浏览器开始就支持

深入探讨一下 overflow 属性的一个很经典的不兼容问题,即 Chrome 浏览器下,如果容器可滚动(假设是垂直滚动),则 padding-bottom 也算在滚动尺寸之内, IE 和 Firefox 浏览器忽略 padding-bottom。

所以我们在实际项目开发的时候,要尽量避免滚动容器设置 padding-bottom 值,除了样式表现不一致外,还会导致 scrollHeight 值不一样,这往往会给开发带来难以察觉的麻烦,需要引起注意。

自 IE8 以上版本的浏览器开始, overflow 属性家族增加了两个属性,就是这里的 overflow-x和 overflow-y,分别表示单独控制水平或垂直方向上的剪裁规则。永远不可能实现一个方向溢出剪裁或滚动,另一方向内容溢出显示的效果。

HTML 中有两个标签是默认可以产生滚动条的,一个是根元素,另一个是文本域<textarea>。之所以可以出现滚动条,是因为这两个标签默认的 overflow 属性值不是visible,从 IE8 浏览器开始,都使用 auto 作为默认的属性值。这也就意味着,从 IE8 浏览器开始,默认状态下是没有滚动栏的,尺寸溢出才会出现,对于 IE7 浏览器,其样式表现就好像设置了 overflow-y:scroll 一般。

Windows 7 系统下的测试和对比发现, IE7 及以上版本 IE、Chrome、 Firefox浏览器滚动栏所占据的宽度均是17px, 注意, 很精准的是17px,
当然,随着以后操作系统的升级,滚动栏的宽度发生变化也是有可能的。

1
2
3
4
5
6
7
8
9
// 获取浏览器滚动栏的宽度
.box { width: 400px; overflow: scroll; }
<div class="box">
<div id="in" class="in"></div>
</div>
console.log(400 - document.getElementById("in").clientWidth);

而 HTML 内容是自上而下加载的,就会发生一开始没有滚动条,后来突然出现滚动条的情况,此时页面的可用宽度发生变化,水平居中重新计算,导致页面发生晃动,这个体验是非常不好的。这里分享一个可以让页面滚动条不发生晃动的小技巧,即使用如下 CSS 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
html {
overflow-y: scroll; /* for IE8 */
}
:root {
overflow-y: auto;
overflow-x: hidden;
}
:root body {
position: absolute;
}
body {
width: 100vw;
overflow: hidden;
}

box-sizing

box-sizing 虽然是 CSS3 属性,但是,让人受宠若惊的是 IE8 浏览器也是支持它的,不过需要加-ms-私有前缀,但 IE9 浏览器开始就不需要私有前缀了。
理论上, box-sizing 可以有下面这些写法:

1
2
3
4
.box1 { box-sizing: content-box; }
.box2 { box-sizing: padding-box; }
.box3 { box-sizing: border-box; }
.box4 { box-sizing: margin-box; }

理论美好,现实残酷。实际上,支持情况如下:

1
2
3
4
.box1 { box-sizing: content-box; } /* 默认值 */
.box2 { box-sizing: padding-box; } /* Firefox 曾经支持 */
.box3 { box-sizing: border-box; } /* 全线支持 */
.box4 { box-sizing: margin-box; } /* 从未支持过 */

min/max-width

IE7 浏览器就支持 min/max-width

为何 box-sizing 不支持 margin-box

100 像素宽的元素,设置个 20 像素大小的 padding 值,offsetWidth 就是 140 像素了,尺寸会变化。你说,一个本身并不会改变元素尺寸的盒子,它有让 box-sizing 支持的道理吗? box-sizing 就是改变尺寸作用规则的! margin 只有在 width 为 auto 的时候可以改变元素的尺寸,但是,此时元素已经处于流动性状态,根本就不需要 box-sizing。 所以,说来说去就是 margin-box本身就没有价值。

另外一个原因牵扯到语义。如果 box-sizing 开了先河支持了 margin-box, margin box 就变成了一个“显式的盒子”, 你让background-origin等属性何去何从,支持还是不支持呢?“margin的背景永远是透明的”这几个大字可是在规范写得清清楚楚,难道让背景色在所谓的 margin box 中也显示?显然是不可能的,我们可以打自己的脸,但是要想让规范打自己的脸,可能吗?

rem

IE8 不支持,

select

原生的<select><option>元素的 innerHTML 只能是纯 text 字符,不能有 html,也不支持伪元素

transparent

transparent 关键字是一个很有意思的关键字

  • background-color:transparent包括 IE6 浏览器都支持,
  • border-color:transparent 从 IE7 浏览器开始支持
  • color:transparent 却从 IE9 浏览器才开始支持。

color:transparent 在 IE9 以上版本的浏览器才支持,原生 IE8 浏览器不支持,会使用默认颜色代替。不要拿兼容模式下的测试结果说事儿,那是不准的。高版本 IE 浏览器下的 IE8 兼容模式 color:transparent 确实可以让文字透明,但是 IE8 用户都是使用原生 IE8 的。

background

IE8 浏览器不认识多背景的写法,自然会忽略第二行声明,只认第一行的 PNG 背景, IE9及以上版本浏览器则会使用后面的声明使用 SVG 图片。

1
2
3
4
.bg {
background: url(icon.png);
background: url(icon.svg), none;
}

linear-gradient

请问如果要区分 IE9 及以下版本和 IE10 及以上版本,该怎么办呢?我们可以这么处理:

1
2
3
4
.bg {
background: url(loading.gif);
background: url(loading.png), linear-gradient(to top, transparent, transparent);
}

IE9 不认识 CSS3 渐变,因此会忽略第二行 CSS 声明。

filter

IE8 浏览器不支持 rgba 半透明背景色,除了使用 PNG 图片外,也可以使用渐变滤镜来兼容。

1
2
3
4
5
6
7
.bgcolor {
background: rgba(0,0,0,.5);
filter: progid:DXImageTransform.Microsoft.gradient (startcolorstr=#7F000000,endcolorstr=#7F000000);
}
:root .bgcolor {
filter: none;
}

让渐变起始色和结束色保持一致,就可以实现纯半透明背景色效果了。在 IE9 浏览器下, rgba半透明和 filter 渐变会同时起作用,因此使用:root 选择器重置了一下。

currentColor

变量是个好东西,可以使用当前 color 计算值,即所谓颜色值。但是同样地, IE9+浏览器才支持它。

###hsl
颜色是 CSS3 才出现的颜色表现格式, IE9+浏览器才支持。

display:inline-block

IE6 和 IE7 浏览器下, block 水平的元素设置 display:inline-block 元素还是 block 水平,也就是还是会自适应容器的可用宽度显示。于是,对于 IE6 和 IE7 浏览器,我们会阴差阳错得到一个比overflow:hidden 更强大的声明,既 BFC 特性加身,又流体特性保留。*zoom: 1 也是类似效果,不过只适用于低级的 IE 浏览器,如 IE7。

line-height 都是有差异

不同系统不同浏览器的默认 line-height 都是有差异,因此,在实际开发的时候,对 line-height 的默认值进行重置是势在必行的。

display:table-cell

其让元素表现得像单元格一样, IE8 及以上版本浏览器才支持。IE浏览器不支持伪元素的display:list-item,这是不使用这个属性进行清除浮动的主要因素,兼容性不好。对于ie浏览器(包括ie11)普通元素设置可以,但是伪类:before和:after就不行。

伪元素

ie7不支持

rgba属性

ie8不支持rgba属性,只能通过半透明图或者使用ie的渐变滤镜实现

内联元素的absolute包含块

但是根据我的测试,在 IE8 至 IE10 浏览器下,图片完全在

容器的左侧外部显示了, IE Edge 中则无此问题。需要给空的元素设置 border 或 padding 让“幽灵空白节点”显现或者直接插入字符才能表现一致。

跨行的兼容性问题在于规范对此行为并未定义,导致浏览器在实现上各有差异。主要差异在于, Firefox 浏览器的“包含块”仅覆盖第一行,而 IE 和 Chrome 浏览器“包含块”的表现完全符合定义,由第一行开头和最后一行结尾的内联盒子共同决定。

placeholder

IE9 及其以下浏览器不支持 placeholder 占位符效果,实际开发的时候,针对这些浏览
器,需要进行模拟。

absolute

IE7 浏览器下,块状的<div>“无依赖绝对定位”的定位表现如同内联的<span>,也就是无论是块级元素还是内联元素,“无依赖绝对定位”后都和内联元素一行显示。

绝对定位元素的这种流体自适应特性从 IE7 就开始支持了很多同行依然使用下面这样的写法:

1
2
3
4
5
6
// 没必要的
.box {
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
}

form

submit 类型按钮在IE7 下有黑框,很难所有浏览器(包括 Firefox 在内的浏览器) UI 完全一致,对视觉呈现是个一挑战。

1
2
3
4
<form>
<input type="submit" id="someID" class="clip">
<label for="someID">提交</label>
</form>

clip

至少在 Chrome 浏览器下, clip 仅仅是决定了哪一部分是可见的,对于原来占据的空间并无影响。然而,并不是所有浏览器都这么认为,在 IE 和 Firefox浏览器下是没有滚动条的,只有光秃秃的一小撮背景色在那里。这又是“未定义行为”的表现,看起来 IE 和 Firefox 对于 clip 渲染采用的是另外的方式。

但是无论怎样,下面这些特性大家的认识都是一致的:使用 clip 进行剪裁的元素其clientWidth 和 clientHeight 包括样式计算的宽高都还是原来的大小,从这一点看,Chrome的渲染似乎更合理。虽然尺寸还是原来的尺寸,但是,隐藏的区域是无法影响我们的点击行为的,说明 clip 隐藏还是很干脆的。

height 百分比值

子元素的 height 百分比值可以生效了( IE8 及以上版本浏览器),所以高度自适应、高度等比例布局等效果都可以从容实现了。

font src

src 表示引入的字体资源可以是系统字体,也可以是外链字体。如果是使用系统安装字体,则使用 local()功能符;如果是使用外链字体,则使用 url()功能符。由于 local()功能符IE9 及其以上版本浏览器才支持,非常实用,而本书目标浏览器包含 IE8 浏览器,因此不做展开

eot 格式是 IE 私有的。注意,目前所有版本的 IE 浏览器都支持 eot 格式,并不是只有 IE6~IE8 支持。只是, IE6~IE8 仅支持 eot 这一种字体格式。

margin:auto

绝对定位元素 margin:auto 居中从 IE8 浏览器开始支持,而普通元素的 margin:auto 居中很早就支持了

z-index

IE6 和 IE7 浏览器有个 bug,就是 z-index:auto 的定位元素也会创建层叠上下文。这就是过去 IE6 和 IE7 的 z-index 会折腾死人的原因。

在过去, position:fixed 和 relative/ absolute在层叠上下文这一块是一样的,都是需要 z-index 为数值才行。但是,不知道什么时候起,Chrome 等 WebKit 内核浏览器下,position:fixed 元素天然层叠上下文元素, 无须 z-index为数值。根据我的测试,目前 IE 和 Firefox 仍是老套路。

unicode-range

IE8 浏览器不支持

border-radius

CSS 圆角属性 border-radius 从 IE9 浏览器才开始支持

nth-of-type

IE8 浏览器不支持

不同浏览器的特点与兼容性

<button>的padding

在 Chrome 浏览器下,我们设置:

1
button { padding: 0; }

按钮的 padding 就变成了 0
但是在 Firefox 浏览器下,左右依然有 padding,可以试试使用:

1
button::-moz-focus-inner { padding: 0; }

而在 IE7 浏览器下,文字如果变多,那么左右 padding 逐渐变大,需要进行如下设置:

1
button { overflow: visible; }

最后,按钮 padding 与高度计算不同浏览器下千差万别,例如:

1
2
3
4
5
button {
line-height: 20px;
padding: 10px;
border: none;
}

结果,在 Chrome 浏览器下是预期的 40 像素,然而 Firefox 浏览器下是莫名其妙的 42 像素,在IE7 浏览器下更是匪夷所思的 45 像素,这使我们平常制作网页的时候很少使用原生的<button>按钮作为点击按钮,而是使用<a>标签来模拟。但是,在表单中,有时候按钮是自带交互行为的,这是<a>标签无法模拟的。这里给大家推荐一个既语义良好行为保留,同时 UI效果棒兼容效果好的实现小技巧,那就是使用<label>元素, HTML 和 CSS 如下:

1
2
<button id="btn"></button>
<label for="btn">按钮</label>

1
2
3
4
5
6
7
8
9
button {
position: absolute;
clip: rect(0 0 0 0);
}
label {
display: inline-block;
line-height: 20px;
padding: 10px;
}

<label>元素的 for 属性值和<button>元素的 id 值对应即可。此时,所有浏览器下的按钮高度都是 40 像素,而且<button>元素的行为也都保留了,是非常不错的实践技巧。

<img>标签的显示

Firefox 浏览器的案例很好地证明了“如果图片没有替换内容,图片就是一个普通的内联标签”。

Chrome 浏览器其实也有类似的表现,只是需要特定的条件触发而已,这个触发条件就是需要有不为空的 alt 属性值。

1
<img alt="任意值">

此时, Chrome 这个<img>宽度也是 100%容器。

为何 IE 浏览器没有 src 属性还是完全的替换元素表现呢?原因就在于 IE 浏览器中有个默认的占位替换内容,当 src 属性缺失的时候,会使用这个默认的占位内容,这也是 IE 浏览器下默认尺寸是 28×30 而不像 Chrome 浏览器那样为 0×0 的原因所在。在高版本的 IE 浏览器下,这个占位的替换内容似乎做了透明处理,但是,在原生的 IE8浏览器下,这个占位内容却全然暴露了

css content属性

Chrome浏览器下,所有的元素都支持 content 属性,而其他浏览器仅在::before/::after 伪元素中才有支持

伪类

IE8 浏览器仅支持单冒号的伪元素

-webkit-私有前缀

滚动条是可以自定义的。因为 IE 浏览器的自定义效果实在是比原生的还要难看,就不浪费大家时间了,就此打住。倒是支持-webkit-前缀的浏览器可以说说。

对-webkit-私有前缀支持良好的浏览器还可以实现多行文字打点效果,但是却无须依赖 overflow:hidden。

1
2
3
4
5
.ell-rows-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}

display:none时的图片加载问题

  • 在 Firefox 浏览器下, display:none 的元素的 background-image 图片是不加载的,包括父元素 display:none 也是如此;
  • Chrome 和 Safari 浏览器,则要分情况,若父元素 display:none,图片不加载,若本身背景图所在元素隐藏,则图片依旧会去加载;
  • IE浏览器而言,无论怎样都会请求图片资源。

<img>元素,则设置 display:none 在所有浏览器下依旧都会请求图片资源。

cursor:none

有一个小问题,就是 IE8 浏览器并不支持 cursor:none 声明,从 IE9 浏览器才开始支持这个属性,怎么办呢?很简单, IE8 浏览器使用自定义的透明光标就可以了。弄一张纯透明的 PNG 图片,然后制作成 cur 格式,就可以实现全部浏览器下的光标隐藏效果了。

对于 Chrome 等浏览器,可以直接使用 PNG 图片作为光标,但是 IE 浏览器不行。 IE 仅支持专门的.cur 格式的光标文件,需要使用工具进行格式转换

font

caption、 icon、 message-box 这 3 个关键字在 Windows 系统下的Chrome 浏览器中似乎是无效的,并不会实时跟着系统字体走,也就是说,就算手动修改了操作系统的字体,这 3 个关键字还是显示浏览器默认的宋体,就算浏览器重启、浏览器升级外加系统重启也没有用;而且, menu 这个关键字表示的并不是“菜单”,而是“调色板标题” small-caption。而所有这些问题在 Firefox 和 IE 浏览器中一个都没有,表现非常一致,非常符合预期,例如,修改“图标”字体为“思源黑体”,如图 8-20 所示,则所有文件名称全部变成了“思源黑体”, 同时 font:icon 所在元素 font-family 计算值也成了“思源黑体”

padding-bottom

如果容器可以滚动,在 IE 和 Firefox 浏览器下是会忽略 padding-bottom 值的,Chrome 等浏览器则不会。

此兼容性差异的本质区别在于: Chrome 浏览器是子元素超过 content box 尺寸触发滚动条显示,而 IE 和 Firefox 浏览器是超过 padding box 尺寸触发滚动条显示。

border-style

:dashed

在 Chrome 和 Firefox 浏览器下,颜色区的宽高比是 3:1,颜色区和透明区的宽度比例是 1:1,而 IE 浏览器则是另外的数据,颜色区的宽高比是 2:1,颜色区和透明区的宽度比例也是 2:1.

:dotted

虚点边框在表现上同样有兼容性差异,虽然规范上明确表示是个圆点,但是 Chrome 以及
Firefox 浏览器下虚点实际上是个小方点, 而 IE 浏览器下则是小圆点.

pc端和移动端的不同

scrollTop

注意,上述规则只对 PC 端有效,对于移动端并不一定适用。例如,在 PC 端,对<html>标签设置 overflow:hidden 可以隐藏滚动条禁止滚动,但是在移动端基本上无效。在 PC 端,窗体滚动高度可以使用 document.documentElement.scrollTop 获取,但是在移动端,可能就要使用 document.body.scrollTop 获取。

fontsize

桌面 Chrome 浏览器下有个 12px 的字号限制

参考资料
浏览器兼容性问题及解决方法
浏览器兼容性问题解决方案 · 总结
再谈ie浏览器兼容问题
Vue.js 不支持 IE8 你们是怎么做的?
天猫即将不支持IE8
前端MVVM框架·avalon2(司徒正美)
如何机智地回答浏览器兼容性问题
浏览器兼容性问题解决方案 · 总结

本文标题:浏览器的兼容性问题解决方案

文章作者:zhyjor

发布时间:2018年04月04日 - 09:04

最后更新:2023年10月11日 - 02:10

原始链接:https://zhyjor.github.io/2018/04/04/浏览器的兼容性问题解决方案/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

🐶 您的支持将鼓励我继续创作 🐶

热评文章