媒介
关于题目多多的IE678,FOUC(flash of unstyled content)——浏览器款式闪灼是一个不可无视的话题,但关于ever green的浏览器就不必剖析了吗?下面尝试较周全地解密FOUC。
究竟什么是FOUC?
页面加载剖析时,页面以款式A衬着;当页面加载剖析完成后,页面倏忽以款式B衬着,致使涌现页面款式闪灼。
款式A,浏览器默许款式 或 浏览器默许款式 层叠 部份已加载的页面款式;
款式B,浏览器默许款式 叠加 悉数页面款式。
为何会涌现FOUC
我们相识当输入网址按回车后浏览器会向服务器发送要求,然后服务器返回页面给浏览器,浏览器边下载页面边剖析边衬着。
下面我们剖解一下边下载页面边剖析边衬着的历程:
边下载边剖析就是边下载html边构建DOM Tree;
浏览器以user agent stylesheet(浏览器内置款式)为质料构建CSSOM Tree;
DOM Tree+CSSOM Tree构建出Render Tree,然后页面内容衬着出来;
当剖析到inline stylesheet 或 internal stylesheet时,立时革新CSSOM Tree,CSSOM Tree或DOM Tree发生变化时会引发Render Tree变化;
当剖析到external stylesheet时就先加载,然后如internal stylesheet那样剖析和革新CSSOM Tree和Render Tree了。
上述步骤5中由于款式文件存在下载这个延时不确定的阶段,因而收集环境不好或款式资本体积大的情况下我们能够看到款式闪灼显著。
这就是为何我们将external stylesheet的引入放在head
标签中的缘由,在body
衬着前先把相对完全的CSSOM Tree构建好。但人人都听说过script
会壅塞html页面剖析(block parsing),而link
不会,那假如收集环境不好或款式资本体积大时,body
已剖析并加入到DOM Tree后,external stylesheet才加载完成,不是也会形成FOUC吗?
style
,link
等款式资本的下载、剖析确切不会壅塞页面的剖析,但它们会壅塞页面的衬着(block rendering)。
Block Parsing 和 Block Rendering的区分
Block Parsing: 壅塞HTML页面剖析,HTML页面会被继承下载,但壅塞点背面的标签不会被剖析,img
,link
等不会发要求猎取外部资本。
Block Rendering:壅塞HTML页面衬着,HTML页面会被继承下载,壅塞点背面的标签会继承被剖析,img
,link
等会继承发送要求猎取外部资本,但不会合成Rendering Tree或不会触发页面衬着,也不会实行JavaScript代码。
各浏览器这方面另有一点差别:
关于Chrome
<link rel="stylesheet">
,<link rel="import">
and @import url("<url>")
会壅塞衬着。
示例1:壅塞剖析
<html>
<body>
<script>
// 打印出 null
console.log(document.getElementById('hi'))
</script>
<script src="./longtime.js"></script>
<div id="hi">Hi</div>
</body>
</html>
示例2:壅塞衬着
<html>
<body>
<script>
// 打印出 <div id="hi">Hi</div>
console.log(document.getElementById('hi'))
</script>
<link rel="stylesheet" href="./longtime.css">
<div id="hi">Hi</div>
</body>
</html>
示例3:壅塞衬着
<html>
<head>
<script>
// 打印出 hinull
console.log('hi' + document.getElementById('hi'))
// 打印出 hiscript#s
console.log('s' + document.getElementById('s'))
</script>
<link rel="stylesheet" href="./longtime.css">
<script id="s"></script>
</head>
<body>
<div id="hi">Hi</div>
</body>
</html>
示例4:壅塞衬着
<html>
<body>
<!-- div#hi在 ./longtime.css下载完前不会被衬着 -->
<style>#hi{color:red;}</style>
<link rel="stylesheet" href="./longtime.css">
<div id="hi">Hi</div>
</body>
</html>
示例2申明,假如壅塞衬着发生在body
标签内,那末body
及其子元素会继承剖析并追加到DOM Tree中;
示例3申明,假如壅塞衬着发生在head
标签内,那末body
及其子元素不会被追加到DOM Tree中。
示例4申明,不论external stylesheet在那里引入,在页面的一切external stylesheets下载完成前,全部页面将不会被衬着。(预计Chrome会预先统计external stylesheet的数目)
关于FireFox
示例1:壅塞衬着
<html>
<body>
<!-- div#hi的笔墨显现为赤色,待./longtime.css下载完后又衬着为其他色彩 -->
<style>#hi{color:red;}</style>
<link rel="stylesheet" href="./longtime.css">
<div id="hi">Hi</div>
</body>
</html>
示例2:壅塞衬着
<html>
<head>
<!-- div#hi不显现,直到./longtime.css下载完后 -->
<style>#hi{color:red;}</style>
<link rel="stylesheet" href="./longtime.css">
</head>
<body>
<div id="hi">Hi</div>
</body>
</html>
关于IE9
示例1:
<html>
<body>
<!-- div#hi没有衬着,也没有加入到DOM Tree中 -->
<style>#hi{color:red;}</style>
<link rel="stylesheet" href="./longtime.css">
<div id="hi">Hi</div>
</body>
</html>
示例2:
<html>
<body>
<!-- div#hi衬着了,加入到DOM Tree中 -->
<style>#hi{color:red;}</style>
<div id="hi">Hi</div>
<link rel="stylesheet" href="./longtime.css">
</body>
</html>
上面的示例表明,IE下block rendering等价于block parsing,由于连img
,script
,link
,@import url()
资本要求都会被壅塞。
处理方法
如今我们晓得FOUC时由于页面采纳暂时款式来衬着页面而致使的,个中唯一chrome能好的屏障了这一点,而其他浏览器就呵呵了。那有什么计划能够处理呢?实在我们的目标就是不要让用户看到暂时款式,那末我们能够隐蔽body
,当款式资本加载完成后再显现body
。
<html class="no-js">
<style>
/*modernizr会将html的no-js替代为js,并将modernizr代码在末了时加载,那末就可以保证一切款式文件已加载完成*/
.no-js body{display: none!important;}
</style>
<body>
<script src="modernizr.js"></script>
</body>
</html>
(编译modernizr时记得勾setClasses哦,不然不会替代no-js的!)
总结
上述计划虽然处理了FOUC的题目,但很显著地延长了首屏白屏时候,当前较盛行的App Shell(能够明白为先显现页面规划的骨架或一幅图片)也会失效,所以关于2C的运用仅仅采纳上述的计划结果并不抱负。后续待我研讨好后再追加一篇吧^_^
尊敬原创,转载请说明来自:http://www.cnblogs.com/fsjohn… ^_^肥仔John
谢谢
Flash of unstyled content
The FOUC Problem
Critical rendering path