02-基础篇:浏览器
juejin_logo copyCreated with Sketch.

前言

在学习CSS神操作骚技巧前,我会通过几章内容讲述CSS的一些基础知识与核心原理,毕竟打下扎实的基本功才能把CSS玩得游刃有余。谈到CSS,就会想到兼容性,想到兼容性就会涉及浏览器,浏览器是一切CSS的运行环境。

浏览器

浏览器指显示万维网媒体信息(文字、图像、音频、视频等)与处理用户交互操作的软件。浏览器是前端开发者每天都打交道的工具,正是它,才有了前端相关职业。

浏览器是Internet时代的产物,随着各种设备操作系统的普及、网络技术的全球化以及人们对信息需求的爆炸式增长,为浏览器的诞生与兴起提供了强大动力,同时也标志着互联网时代的到来。

组成

虽然目前市场上的浏览器品牌众多,但浏览器的结构还是由以下部分组成。

  • 地址栏:用于输入网页地址,通过识别地址信息跳转到相应网页
  • 菜单栏:包括设置内容与常见快捷操作,用户可自定义设置内容
  • 标签栏:包括一个或多个窗口,窗口内容互不干扰,独立运行
  • 窗口栏:用于显示当前网页地址的访问内容,为用户提供各种交互操作
  • 状态栏:用于实时显示当前操作与网页下载的进度情况
历史

浏览器作为一个跨时代的科技产物,为现代网络人机交互的发展提供了强而有力的支持,历史的时刻不应被忘记,以下简单列举一些浏览器的历史时刻。

  • 1993年NCSA组织发布Mosaic浏览器
  • 1994年网景公司发布Navigator浏览器
  • 1995年微软公司发布IExplorer浏览器,同时掀起浏览器之战
  • 1996年Navigator的市场份额达到86%,微软公司开始将IExplorer整合到Windows系统
  • 1996年欧朋公司发布Opera浏览器
  • 1998年,网景公司启动其开源产品,开始推出Mozilla
  • 2001年,为人诟病的IExplorer 6发布,这货霸占国内市场十多年
  • 2002年网景公司发布Firefox浏览器
  • 2003年苹果公司发布Safari浏览器
  • 2004年IExplorer的市场份额达到历史顶峰92%,自此以后其市场份额开始下滑
  • 2006年Firefox 3的发布创下吉尼斯世界纪录,一天800万下载量
  • 2008年谷歌公司发布Chrome浏览器

到此世界五大浏览器鼎立的格局逐渐形成,也为后期浏览器市场的多变提供了广大的技术支持。浏览器发展史并不久远,虽然只有短短的20多年,但却不断在更新迭代,为广大互联网用户提供越来越强大的人机交互功能。

世界五大浏览器

包括ChromeSafariFirefoxOperaIExplorer/Edge

渲染引擎

渲染引擎又称浏览器内核,指负责对网页语法解析并渲染为一张可视化网页的解析器。它是浏览器最核心最重要的部位,不同内核对网页语法的解析也有不同,因此同一网页语法在不同内核的浏览器中的渲染效果也可能不同,这就是浏览器差异性

上述提到的世界五大浏览器,在自身发展时都使用了一种或多种渲染引擎作为自身的渲染引擎。

  • Google ChromeWebkit(前期)、Blink(后期)
  • Apple SafariWebkit
  • Mozilla FirefoxGecko
  • ASA OperaPresto(前期)、Blink(后期)
  • Microsoft IExplorerTrident
  • Microsoft EdgeTrident(前期)、Blink(后期)

IExplorerEdge同是微软公司开发的浏览器产品,鉴于IExplorer存在很多为人诟病的问题,在后续的系统升级中逐渐使用Edge取代IExplorerWindows系统中的位置。

因为世界五大浏览器在所有浏览器产品中占领着巨大的市场份额,因此在20多年的浏览器发展史中,被大规模使用的渲染引擎也就是那几个浏览器相应渲染引擎。

  • Blink内核:由谷歌公司与欧朋公司合作自研的内核,同时谷歌公司也将其作为开源内核架构Chromium的一部分发布出来,在Chrome 28+Opear 15+中被使用
  • Webkit内核:由苹果公司自研的内核,同时也是Blink内核的原型,在Chrome 1~28Safari 1+中被使用
  • Gecko内核:由网景公司自研的内核,前期在Navigator中使用,后期推广到Firefox中,在Firefox 1+中被使用
  • Presto内核:由欧朋公司自研的内核,其渲染性能达到极致但牺牲了兼容性,目前已废弃,在Opear 7~14中被使用
  • Trident内核:由微软公司自研的内核,因为其被包括在全世界使用率最高的Windows系统中,导致一直称霸渲染引擎界十多年,在IExplorer 4+中被使用

以下加插两个小故事,虽然不是什么大事件,但也是浏览器发展史中较有趣的故事,了解了解也无妨。

Gecko内核由来

Gecko内核的诞生其实跟IExplorer还是有点关系的。早期IExplorer不使用W3C标准,导致微软公司一些开发者很不满,他们出走并与网景公司一些开发者共同创办了Mozilla,以当时Mosaic内核为基础重新开发出Gecko内核

浏览器大战

微软公司的IExplorer曾经与其他浏览器发生过两次世界大战,因为其垄断性质的操作也导致其在2014年后开始慢慢走向衰落,直至2022年被官方宣布完全放弃。

第一次发生在1995~1998年,当时微软发布IExplorer,但网景公司的Navigator的市场份额已达到86%,迫使微软公司将IExplorer植入到全世界使用率最高的Windows系统中,相当于买电脑送浏览器,这种操作让IExplorer在极短时间内超过了Navigator的市场份额,导致后续与网景公司的Navigator大打出手,最后网景公司将Navigator卖给AOL公司为收场结束这次浏览器大战。

第二次发生在2003~2022年IExplorer通过其自身的优势取得了很好的市场份额,巨大的使用量让其开始蚕食其他浏览器的市场份额,但很多后起之秀的浏览器,例如SafariFirefoxOperaChrome,还有众多国产浏览器,都积极通过各种技术手段并推出更多用户功能的方式对抗IExplorer的打压。经过十多年的竞争,以Chrome为首的浏览器在2018年终于反超IExplorer的市场份额并一步一步拉开差距,最终IExplorer2022年被官方宣布完全放弃。

一代浏览器之王IExplorer就此落幕。


推荐一个统计互联网市场份额的网站StatCounter,可根据需求查询不同浏览器的统计数据。以后产品经理让你兼容某些落后浏览器,你可把浏览器市场份额统计数据全盘搬出,大声并自信地告诉TA:现在几乎无人使用XX浏览器了。

渲染过程

要了解浏览器网页的渲染过程,首先得知道关键渲染路径关键渲染路径指浏览器从最初接收请求得到HTMLCSSJS等资源,然后解析、构建、渲染、布局、绘制和合成,到最后呈现在用户眼前的整个过程。

将关键渲染路径划分理解,那网页的渲染过程可分为以下部分。

  • 解析文件
    • DOM树:将html文件转换为DOM树
    • CSSOM树:将css文件转换为CSSOM树
    • 渲染树:将DOM树CSSOM树合并生成渲染树
  • 绘制图层
    • 回流:根据渲染树生成布局渲染树
    • 重绘:根据布局渲染树生成绘制渲染树
  • 合成图层:根据绘制渲染树合成图层显示在屏幕中
解析文件

HTML文档描述网页的结构,浏览器通过HTML解析器HTML解析为DOM树结构HTML文档中所有内容皆为节点,各节点间拥有层级关系,彼此相连,组成DOM树

构建DOM树的过程:读取HTML文档字节(Bytes),将字节转换成字符(Chars),根据字符确定标签(Tokens),将标签转换成节点(Nodes),以节点为基准构建DOM树

CSS文档描述网页的表现,浏览器通过CSS解析器CSS解析为CSSOM树结构,与DOM树结构较像。CSS文档中所有内容皆为节点,与HTML文档中的节点一一相应,各节点间拥有层级关系,彼此相连,组成CSSOM树

构建CSSOM树的过程:读取CSS文档字节(Bytes),将字节转换成字符(Chars),根据字符确定标签(Tokens),将标签转换成节点(Nodes),以节点为基准构建CSSOM树。与DOM树的构建过程完全一样。

在构建DOM树时,当HTML解析器遇到<script>时会立即阻塞DOM树的构建,将控制权移交给浏览器的JS引擎,等到JS引擎运行完毕,浏览器才会从中断的地方恢复DOM树的构建。

<script>的脚本加载完毕,JS引擎通过DOM APICSSOM API操作DOM树CSSOM树。为何会产生渲染阻塞?其根本原因在于JS操作DOM后,浏览器无法预测未来DOM的具体内容,为了防止无效操作与节省资源,只能阻塞DOM树的构建。

渲染过程

浏览器的渲染引擎将DOM树CSSOM树合并生成渲染树,只渲染需显示的节点及其样式。DOM树CSSOM树渲染树三者的构建并无先后条件先后顺序,非完全独立而是存在交叉并行构建的情况,因此会形成一边加载,一边解析,一边渲染的工作现象。

绘制图层

进入绘制阶段,遍历渲染树,调用渲染器的paint()在屏幕中绘制内容。根据渲染树布局计算样式,即每个节点在网页中的布局、尺寸等几何属性。HTML默认是流式布局,CSSJS会打破这种布局,改变DOM的几何属性与外观属性。在绘制时根据渲染树布局,再根据布局绘制,这就是回流重绘

在此涉及两个核心概念:回流重绘。我用两句精简的话概括它们。

  • 回流:改变几何属性的渲染
  • 重绘:改变外观属性而不影响几何属性的渲染

当生成渲染树后,至少会渲染一次,在后续交互时还会不断地重新渲染。这时只会回流重绘只有重绘,因此引出一个定向法则:回流必定引发重绘,重绘不一定引发回流

我会安排下章讲述回流重绘以及如何让它们的影响最小化。相信下章提到的属性排序可能较少同学了解过或使用过,敬请期待。

合成图层

将回流重绘生成的图层逐张合并并显示在屏幕中。上述几个步骤并非一次性顺序完成,若改动DOM/CSSOM,上述过程会被重新执行,实际上CSSJS往往会多次改动DOM/CSSOM。简而言之,用户的交互操作引发了网页的重渲染。

兼容性

兼容性又称网页兼容性,指网页在各种浏览器中的显示效果可能不同而产生浏览器与网页间的兼容问题。

说到兼容性,就不得不推荐一个专门为开发者定制可查询W3C标准在各种浏览器中兼容性的网站Caniuse,可快速了解W3C标准在各个浏览器中的表现。后续遇到陌生的CSS属性与选择器都可使用Caniuse查看它们的兼容性。

产生浏览器间的兼容问题,正是渲染引擎在渲染网页时因为某些差异而导致的。在网页的设计与开发中,做好浏览器兼容才能让网页在不同浏览器中都能显示正常。浏览器对标准的更好兼容能够给用户带来更好的使用体验,当然无法奢求浏览器厂商能统一所有浏览器标准,所以开发者只能自己着手解决了。

以下聊聊处理CSS兼容性的三种解决方案,相对处理JS兼容性来说更简单,这也是普遍开发者认为CSS简单的原因之一。

磨平浏览器默认样式

每个浏览器的CSS默认样式不尽相同,所以最简单最有效的方式就是对其默认样式初始化。以下默认样式初始化的代码简单暴力但不明确,*通配符可是有执行性能问题的。

* {
	margin: 0;
	padding: 0;
}

推荐两种磨平浏览器默认样式的方式,在接入其他css文件前将其导入,天下太平,大家都不能拼爹了,都是在同一起跑线上,IExplorer同学你可别抢跑哇,大家都盯着你呢!

  • normalize.css:懒人必备的浏览器默认样式,接近40kStar,说明很多人都是懒人
  • reset.css:我自定义的默认样式,大家也可自行为所有应用撰写一份默认样式

在应用入口文件的其他css文件前导入默认样式文件。

import "path/to/normalize.css";
// 或
import "path/to/reset.css";
加入浏览器私有属性

通常编写CSS都会在一些CSS3属性前加入-webkit--moz--ms--o-,这些奇形怪状写到手软的东西就是浏览器私有属性。样式少还好,样式多那就欲哭无泪了。

出现这些私有属性,是因为制定CSS标准W3C组织其动作就像蜗牛一样慢,量产一个属性需走一个很严格很复杂的流程。一个成熟且被大众肯定的属性,浏览器厂商会加大其支持力度而铺路,但为了避免日后W3C组织公布标准属性时有所变更,就加入一个本厂商的私有属性提前支持该属性,待W3C组织公布该标准属性后,再让新版浏览器支持该标准属性。

对于编写私有属性的顺序需特别注意:兼容性写法放到前面,标准性写法放到最后。在浏览器解析CSS时,若标准属性无法使用则使用当前浏览器相应私有属性。

/* Chrome、Safari、New Opera、New Edge */
-webkit-transform: translate(10px, 10px);
/* Firefox */
-moz-transform: translate(10px, 10px);
/* IExplorer、Old Edge */
-ms-transform: translate(10px, 10px);
/* Old Opera */
-o-transform: translate(10px, 10px);
/* 标准 */
transform: translate(10px, 10px);

当然不是所有CSS3属性都需补齐-webkit--moz--ms--o-,上述代码只是一个示例,真正的transform私有属性只有-webkit--ms-。这些私有属性需查看Caniuse以确保编写正确,若想偷懒也可全部写上。

每个CSS3属性都编写这么一堆兼容性代码,无疑是对生命最大的浪费。在使用webpack打包代码时,可接入postcss-loaderpostcss-preset-envpostcss-preset-env内置了autoprefixer,它会根据Caniuse提供的数据对代码中的CSS3属性批量加入私有属性。

若使用bruce-app,那也无需关注私有属性,因为其内置了postcss-loaderpostcss-preset-env。自动化工具的好处就是为了解决一些重复而无趣的工作。

CSS Hack

CSS Hack指针对不同浏览器编写不同CSS,让它能够同时兼容不同浏览器,在不同浏览器中渲染想要的效果。当然也可反过来利用CSS Hack为不同版本的浏览器定制不同效果。

在一些老旧网页的html文件css文件中可能会看到以下代码,没错,这就是CSS Hack。现在可能很多同学都不会遇到这种写法,毕竟很多公司的网站都放弃了IExplorer 8以下的兼容,这些痕迹都已成为历史。很多同学可能未想过那些老开发者是多么苦逼的,光兼容IExplorer就够烦了,还连续兼容几个版本。

<head>
	<!--[if IE]>
	<style>
	.elem {
		background-color: #f66;
	}
	</style>
	<![endif]-->
</head>
.elem {
	background-color: #f66; /* IExplorer 8+ */
	*background-color: #f66; /* IExplorer 7 */
	_background-color: #f66; /* IExplorer 6 */
}

所以现在也不会推荐学习这些CSS Hack,有一个基本了解即可。上述CSS Hack只是最简单的几行代码,其实还存在一些更难的表达式。当然也不推荐这种写法,毕竟不符合大名鼎鼎的雅虎军规Avoid CSS Expressions


综上所述,结合磨平浏览器默认样式加入浏览器私有属性这两种方式完成浏览器兼容性的处理即可。

IExplorer兼容性

顺带提一个众多开发者觉得很头疼的问题,就是IExplorer兼容性。对于现在的同学来说还好,我在2015年转行前端时,有些面试的公司会要求兼容IExplorer 5IExplorer 6。试问下,兼容一个90年代末00年代初的浏览器版本,是一个多费劲的事情啊!刚好又遇到HTML5CSS3的迅速发展,是一个技术的取舍问题,要么原地踏步要么紧跟潮流,我最终还是选择了后者。

正是IExplorer的垄断性与很多网站在早期是基于IExplorer 6开发与维护的,导致后期的用户都是优先使用IExplorer 6,也就造成很多公司招聘开发者都要标配处理IExplorer兼容性。我当时也是凭着处理IExplorer兼容性的技能才顺利转行,不然现在还蹲在医院当个苦逼的医生呢!

IExplorer的垄断性使得Trident内核在十多年中一家独大,微软公司可能很有信心吧,在很长时间内都无更新Trident内核,导致其曾经与W3C标准完全脱节,大量安全隐患无法得到解决。看过jquery源码的同学都知道,源码中包括大量IExplorer兼容代码,所以在移动端中使用jquery操作DOM是一件费力不讨好的事情,后面才出现一个叫zepto的库代替jquery在移动端中的使用,该库很小,因为删除了所有IExplorer兼容代码

在此我也建议,在业务需求允许的范围内不要兼容IExplorer,毕竟兼容IExplorer需花费很多时间维护,更何况微软公司已宣布完全放弃IExplorer的维护而转向Edge

本课程的核心内容CSS神操作骚技巧都是基于CSS3CSS4,若需兼容IExplorer,那我创作本课程就无任何意义了。因为IExplorer压根不兼容后面提到的很多CSS神操作骚技巧。我曾经在自己公众号粉丝群与几位同学聊过一些浏览器兼容问题,简括了一句:不搞IExplorer兼容,那就无兼容问题

目前很多国产浏览器都是基于开源内核架构Chromium二次开发,可认为是Chrome外面又包了一层外壳。另外可能有些国产浏览器打着双内核的旗号,在Blink内核的基础上又增加一个Trident内核Blink内核相应浏览器的极速模式,可访问一些较现代化与技术超前的网站,例如官方网站、游戏网站、视觉网站、可视化网站等;Trident内核相应浏览器的兼容模式,可访问一些久经不衰的网站,例如政府网站、政务网站、金融网站等。

留言
Ctrl + Enter
全部评论(34)
八岁小孩学编程的头像
删除
我的天 写的太好了吧
点赞
回复
wzw的头像
删除
前端工程师
paint()函数怎么可以看的到啊,想看看
点赞
回复
wzw的头像
删除
前端工程师
为了防止无效操作和节省资源,阻塞DOM树的构建。这里为什么会无效操作和节省资源呀,不太理解,有例子没有呀
1
2
删除
私下理解,可以理解为一个dom节点生成,但是是通过js文件去控制是否需要显示的,如果先执行完dom树的完整预先生成,js文件又控制不需要生成,就白生成了,会形成浪费,所以会阻塞
点赞
回复
删除
懂了[呲牙]
私下理解,可以理解为一个dom节点生成,但是是通过js文件去控制是否需要显示的,如果先执行完dom树的完整预先生成,js文件又控制不需要生成,就白生成了,会形成浪费,所以会阻塞
点赞
回复
只要锄头舞的好的头像
删除
前端开发工程师 @ 中银商务
我觉得你做医生可能更好,加班加成狗
2
1
删除
(作者)
我现在后悔不继续当医生了
1
回复
遨翔在知识的海洋里的头像
删除
web前端工程师 @ 华为
将DOM树和CSSOM树合并生成渲染树:是不是把对应的css内联进html中,实际还是生成的render树就是带有css属性的DOM树,还是说有render树?(我在astexplorer.net中没有找到render渲染树)
1
回复
程_风破浪的头像
删除
在座的都是有钱银[看]
2
回复
只想过平凡生活的迪迪的头像
删除
前端开发 @ 上海
大佬牛逼!!!!
点赞
回复
xiaomeimei的头像
删除
前端工程师
大神之前真的是个医生吗
1
1
删除
(作者)
是呀,放射科医生
8
回复
一个兴趣使然的切图仔的头像
删除
我想问下几何属性该怎么理解?
点赞
1
删除
(作者)
例如布局、尺寸等可用数学几何衡量的属性
2
回复
Mingo-233的头像
删除
特别注意:兼容性写法放到前面,标准写法放到最后。为啥?我反过来写会有什么影响吗?只要有一种写法能被当前浏览器读取出来不就行了吗?
1
6
删除
同问
点赞
回复
删除
我觉得这应该是跟CSS的样式覆盖有关系(相同权重的情况下,后面的覆盖前面的)。标准写法放到最后,会覆盖掉前面的兼容性写法,这样写表示默认使用浏览器最新的标准属性,如果标准属性无法使用的情况下就会去使用当前浏览器对应的私有属性。而反过来写的话,则表示默认使用私有属性,和前者相反。
----
感觉说了一大堆废话,直接看例子吧
展开
3
回复
查看更多回复
郭二蛋的头像
删除
前端 @ 国际庄某养猪场
大名鼎鼎的雅虎军规 哈哈
2
回复
小樵泉渡的头像
删除
IExplorer同学你可别抢跑哇,大家都盯着你呢!
2
回复
lumi41803的头像
删除
web前端开发
动作像蜗牛一样的W3C把我看乐了
3
回复
cch12的头像
删除
初初初级前端 @ njtmmj
Firefox少了个x,小菜鸟发现的一出文字丢失,哈哈哈
1
1
删除
(作者)
修改了
点赞
回复
旋风冲锋的头像
删除
先讲前置知识很棒
1
1
删除
(作者)
这些前置知识很重要,是CSS非常重要的组成部分
2
回复
暮良的头像
删除
我给作者发了邮箱,不知道作者会不会回复我😜
点赞
1
删除
(作者)
发了哪个邮箱呀😁
点赞
回复