四大内核: Blink、Gecko、WebKit、Trident (不再活跃)
主流浏览器:
IE(Trident内核)、Firefox(火狐:Gecko内核)、Safari(苹果:webkit内核)、Google Chrome(谷歌:Blink内核)、Opera(欧朋:Blink内核)
W3C对标准的推进,Firefox,Chrome,Safari,Opera的出现,结束了IE雄霸天下的日子。
然而,这对开发者来说,是好事,也是坏事。
说它是好事,是因为浏览器厂商为了取得更多的市场份额,会促使各浏览器更符合W3C标准,而得到更好的兼容性,并且,不同浏览器的扩展功能(例如 -moz,-webkit 开头的样式),对W3C标准也是个推进;
说它是坏事,因为,多个浏览器同时存在,这些浏览器在处理一个相同的页面时,表现有时会有差异。这种差异可能很小,甚至不会被注意到;也可能很大,甚至造成在某个浏览器下无法正常浏览。我们把引起这些差异的问题统称为“浏览器兼容性问题”。而正是这些“浏览器兼容性问题”,无形中给我们的开发增加了不少难度。
是指 不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的效果。
即:同样的代码,在不同的浏览器上显示的页面效果不一样。
浏览器各浏览器使用了不同的内核,并且它们处理同一件事情的时候思路不同。
从浏览器内核的角度来看,浏览器兼容性问题可分为以下三类:
不规则的嵌套:
<div>
<li>新闻标题一</li>
<li>新闻标题一</li>
<li>新闻标题一</li>
</div>
div 中直接嵌套 li 元素是不合标准的,li 应该处于 ul 内。此类问题常见的还有 p 中嵌套 div, table等元素。
不规范的DOM接口和属性设置:
document.all.a_name.style.top = 35;
上面代码中 top 的值,其实应该是一个字符串值,需有单位。例如:35px。
总之,人为的原因也占很大一部分。而人为造成兼容性问题的原因,除了粗心之外,大都源于浏览器bug的存在,和开发者对标准的不了解。
比如,如果要做一个功能,功能是想让鼠标悬停在 img 元素上方时,可以出现提示信息,经常针对 IE 做开发的人,可能会使用 img 元素的 “alt” 属性,但其他浏览器中就是不给 “alt” 属性面子。因为 W3C 标准中规定要去做这件事的属性是 “title”,大多浏览器符合标准,IE 不符合,这是 IE 浏览器内核的问题;开发者不知道 “title” ,不遵循标准去写代码,是开发者的问题。
所以,一个问题分两半,浏览器和开发者都有责任。既然都有责任,就都有义务去解决兼容性问题。那么,从浏览器的角度来讲,它的厂商应该修复浏览器的 bug 和不合标准的地方,当某一天 IE 的 “alt” 不能用于提示了,还有人用这个错误的属性去显示提示么?
从开发者角度来讲,多了解标准,了解浏览器兼容性问题,就可以在开发的过程中,有效的避开兼容性问题,让你的页面在所有浏览器中畅通无阻。
(1)从产品的角度看:产品的受众、受众的浏览器比例、效果优先还是基本功能优先。
(2)成本的角度:有无必要做这个兼容。
让哪些浏览器 支持 哪些效果
(1)根据兼容需求选择技术框架/库(如 jquery 1.x.x )。
(2)根据兼容需求选择兼容工具: html5shiv 、 Respond.js 、 CSS Reset 、 normalize.css 、 Modernizr.js 、 postcss 。
(3)条件注释、 CSS Hack 、 js 能力检测做一些修补。
Hack : CSS 中, Hack 是指一种兼容 CSS 在不同浏览器中正确显示的技巧方法,修补 bug 的方法。
Filter :表示过滤器的意思,它是一种对特定的浏览器或浏览器组显示或隐藏规则或声明的方法。本质上讲, Filter 是 hack 方法中的一种。
这里推荐一个网站,把css转换成兼容的
http://autoprefixer.github.io/
推荐https://caniuse.com/这个查询网站。它是一个针对前端开发人员定制的一个查询CSS、JS、HTML5、SVG在主流浏览器中特性和兼容性的网站,可以很好的保证网页在浏览器中的兼容性。有了这个工具我们就可以快速的了解到代码在各个浏览器中的兼容情况了,强烈推荐一波
(1)渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
(2)优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
原因:
IE10浏览器解析不了es6的语法,需要我们使用babel(Babel是一种工具链,主要用于将ECMAScript 2015+代码转换为当前和旧版浏览器或环境中的向后兼容版本的JavaScript)。但是Babel 默认只转换新的 JavaScript 语法(syntax),而不转换新的 API ,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。
解决方法1:babel-polyfill
在vue项目中安装babel-polyfill,polyfill翻译过来叫做垫片/补丁。就是用社区上提供的一段代码,让我们在不兼容某些新特性的浏览器上,使用该新特性。
npm install --save-dev babel-polyfill
然后在mian.js中引入babel-polyfill(要在引入vue,vuex,elementui 之前引入,直接写在第一句)
import ‘babel-polyfill’;
注意: vue不持之ie8 以及之前的版本
这里介绍的是babel-polyfill的完整导入,如果为了性能考虑,你还可以针对ie的报错信息进行自动按需导入,如promise之类。
解决方法2:core-js
你可能听过’babel-polyfill’,babel-polyfill 融合了 core-js 和 regenerator-runtime,因此’babel-polyfill’ 本质就是’corejs’。
core-js 是 babel-polyfill 的底层依赖,通过各种奇技淫巧,用 ES3 实现了大部分的 ES2017 原生标准库,同时还要严格遵循规范。
npm i --save core-js
在main.js入口文件中引入:
2.'core-js' 导入几种形式:
// 导入所有新提案api
import "core-js";
// 唯一稳定的'core js'功能-es和web标准
import "core-js/stable";
// 仅支持稳定的ES功能
import "core-js/es";
// 只导入指定api
import "core-js/features/set";
import "core-js/stable/set";
import "core-js/es/set";
总结:简单使用,不太考虑优化: 1.npm i --save core-js 2.main.js入口文件中导入import “core-js”;
推荐使用:兼容性推荐使用core-js,因为core-js包含了babel-polyfill,且babel-polyfill已经逐步放弃使用了
attachEvent ——兼容:IE7、IE8;不兼容 firefox、chrome、IE9、IE10、IE11、safari、opera。
addEventListener——兼容:firefox、chrome、IE、safari、opera;不兼容 IE7、IE8
function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) { // W3C标准
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent) { // IE
var r = elm.attachEvent('on' + evType, fn); // IE5+
return r;
} else {
elm['on' + evType] = fn; // DOM事件
}
}
e = ev || window.event
scrollTop = document.documentElement.scrollTop || document.body.scrollTop
if (e.stopPropagation) {
e.stopPropagation()
} else {
e.cancelBubble = true
}
link.onclick = function(event) {
// 执行自定义逻辑
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
return false;
};
Firefox下,可以使用 const 关键字或 var 关键字来定义常量;IE下,只能使用 var 关键字来定义常量。
解决方案:统一使用 var 关键字来定义常量。
IE下,event 对象有 x、y 属性,但是没有 pageX、pageY属性;Firefox下,event 对象有pageX、pageY属性,但是没有 x、y属性。
var myX = event.x ? event.x : event.pageX;
var myY = event.y ? event.y : event.pageY;
在Firefox下需要用CSS禁止选取网页内容,在IE用JS禁止
-moz-user-select: none; // Firefox
obj.onselectstart = function {return false;} // IE
使用ormalize.css 抹平差异,同时可以定制自己的 reset.css,例如通过通配符选择器或者标签选择器(推荐),全局重置样式
写法 | 内核 | 浏览器 |
---|---|---|
-webkit- | webkit渲染引擎 | chrome/safari |
-moz- | gecko渲染引擎 | Firefox |
-ms- | trident渲染引擎 | IE |
-o- | opeck渲染引擎 | Opera |
.box{
height: 40px;
background-color: red;
color: #fff;
border-radius: 5px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
可以使用 Autoprefixer
是一个用于自动添加 CSS 浏览器前缀的工具,以确保你的样式在不同浏览器中正确地显示。它可以根据 Can I Use 数据库来确定需要添加哪些前缀,以满足特定的浏览器兼容性要求。
安装Autoprefixer
npm install autoprefixer --save-dev
配置 Autoprefixer:
// .browserslistrc
last 2 versions
> 1%
IE 11
// 这个配置表示支持最新的两个浏览器版本
// 全球使用率超过1%的浏览器,以及 Internet Explorer 11。
使用 Autoprefixer:
const autoprefixer = require('autoprefixer');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
autoprefixer(),
],
},
},
},
],
},
],
},
};
在上述示例中,postcss-loader 用于调用 Autoprefixer 插件。
Autoprefixer 会根据你指定的目标浏览器版本自动添加适当的前缀,以确保样式在这些浏览器中正确渲染。这简化了开发人员在编写样式时考虑兼容性的工作。
img{border:none}
Firefox/Chrome/Safari/Opera浏览器使用opacity;IE浏览器使用filter
opacity: 0.7; /*FF chrome safari opera*/
filter: alpha(opacity:70); /*用了ie滤镜,可以兼容ie*/
统一使用 {cursor:pointer}
按照link–visited–hover–active 的顺序编写
p{font-size: 12px; transform: scale(0.8);}
http://autoprefixer.github.io/
-webkit-touch-callout:none
-webkit-user-select:none
"off" autocorrect="off" />
input::-webkit-input-speech-button {display: none}
* {-webkit-tap-highlight-color:rgba(0,0,0,0);}
input有placeholder情况下不要设置行高
-webkit-overflow-scrolling: touch;
需要将时间中的’00:00:00去除之后才能转为时间戳’