资讯专栏INFORMATION COLUMN

前端魔法堂:解秘FOUC

MRZYD / 1343人阅读

摘要:前言对于问题多多的,浏览器样式闪烁是一个不可忽视的话题,但对于的浏览器就不用理会了吗下面尝试较全面地解密。示例说明,不管在哪里引入,在页面的所有下载完成前,整个页面将不会被渲染。

前言

 对于问题多多的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

, and @import url("")会阻塞渲染。
示例1:阻塞解析


  
    
    
    
Hi

示例2:阻塞渲染


  
    
    
    
Hi

示例3:阻塞渲染


  
    
    
    
  
  
    
Hi

示例4:阻塞渲染


  
        
    
    
    
Hi

示例2说明,如果阻塞渲染发生在body标签内,那么body及其子元素会继续解析并追加到DOM Tree中;
示例3说明,如果阻塞渲染发生在head标签内,那么body及其子元素不会被追加到DOM Tree中。
示例4说明,不管external stylesheet在哪里引入,在页面的所有external stylesheets下载完成前,整个页面将不会被渲染。(估计Chrome会预先统计external stylesheet的数量)

对于FireFox

示例1:阻塞渲染


  
        
    
    
    
Hi

示例2:阻塞渲染


  
        
    
    
  
  
    
Hi
对于IE9

示例1:


  
        
    
    
    
Hi

示例2:


  
        
    
    
Hi

上面的示例表明,IE下block rendering等价于block parsing,因为连img,script,link,@import url()资源请求都会被阻塞。

解决方法

 现在我们知道FOUC时由于页面采用临时样式来渲染页面而导致的,其中仅有chrome能好的屏蔽了这一点,而其他浏览器就呵呵了。那有什么方案可以解决呢?其实我们的目的就是不要让用户看到临时样式,那么我们可以隐藏body,当样式资源加载完成后再显示body


    
    
        
    

(编译modernizr时记得勾setClasses哦,否则不会替换no-js的!)

总结

 上述方案虽然解决了FOUC的问题,但很明显地延长了首屏白屏时间,当前较流行的App Shell(可以理解为先显示页面布局的骨架或一幅图片)也会失效,所以对于2C的应用仅仅采用上述的方案效果并不理想。后续待我研究好后再追加一篇吧^_^
 尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohn... ^_^肥仔John

感谢

Flash of unstyled content
The FOUC Problem
Critical rendering path

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82594.html

相关文章

  • 前端魔法解秘FOUC

    摘要:前言对于问题多多的,浏览器样式闪烁是一个不可忽视的话题,但对于的浏览器就不用理会了吗下面尝试较全面地解密。示例说明,不管在哪里引入,在页面的所有下载完成前,整个页面将不会被渲染。 前言  对于问题多多的IE678,FOUC(flash of unstyled content)——浏览器样式闪烁是一个不可忽视的话题,但对于ever green的浏览器就不用理会了吗?下面尝试较全面地解密F...

    Dean 评论0 收藏0
  • 前端魔法解秘FOUC

    摘要:前言对于问题多多的,浏览器样式闪烁是一个不可忽视的话题,但对于的浏览器就不用理会了吗下面尝试较全面地解密。示例说明,不管在哪里引入,在页面的所有下载完成前,整个页面将不会被渲染。 前言  对于问题多多的IE678,FOUC(flash of unstyled content)——浏览器样式闪烁是一个不可忽视的话题,但对于ever green的浏览器就不用理会了吗?下面尝试较全面地解密F...

    VEIGHTZ 评论0 收藏0
  • 前端魔法——调用栈,异常实例中的宝藏

    摘要:前言在上一篇前端魔法堂异常不仅仅是中我们描述出一副异常及如何捕获异常的画像,但仅仅如此而已。调用方从右到左的顺序将参数压入栈中,在被调用方执行完成后,由被调用方负责清理栈中的参数也称为栈平衡。 前言  在上一篇《前端魔法堂——异常不仅仅是try/catch》中我们描述出一副异常及如何捕获异常的画像,但仅仅如此而已。试想一下,我们穷尽一切捕获异常实例,然后仅仅为告诉用户,运维和开发人员页...

    wangjuntytl 评论0 收藏0
  • CSS魔法:更丰富的前端动效by CSS Animation

    摘要:无效生效重复怎么办与规则一样,标准规定相同的关键帧不产生层叠,仅最后出现的认定为有效。但实际上和均将关键帧设计为可层叠的。为默认值,表示动画一结束,动画效果就结束表示动画一开始就马上执行完第一个关键帧的效果。 前言  在《CSS魔法堂:Transition就这么好玩》中我们了解到对于简单的补间动画,我们可以通过transition实现。那到底多简单的动画适合用transtion来实现呢...

    MrZONT 评论0 收藏0
  • 前端魔法——异常不仅仅是try/catch

    摘要:我打算分成前端魔法堂异常不仅仅是和前端魔法堂调用栈,异常实例中的宝藏两篇分别叙述内置自定义异常类,捕获运行时异常语法异常网络请求异常事件,什么是调用栈和如何获取调用栈的相关信息。 前言  编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外。对于业务用例的例外我们别无它法,必须要求实施人员与用户共同...

    bladefury 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<