Flash of Unstyled Content (FOUC) 之答疑解惑

这几天在学习一些前端的知识,发现了一个之前闻所未闻的术语Flash of Unstyled Content (FOUC),貌似很高端大气上档次。于是查阅了一些英文的资料,要一探究竟。

FOUC是神马

其实平时我们也大有可能接触到FOUC,只不过它认得你,而你不认得它。你也许看到过这样的现象:页面开始没有成功加载样式,但是几秒钟后又看到页面渲染后的样子,这就是FOUC,身在墙中的你是不是深有体会啊。在前端设计领域,这种现象用术语”Flash of Unstyled Content“称呼它,简称为FOUC。下图就展示了CNN英文主页加载CSS失败时,出现FOUC现象的一个例子。

Flash of Unstyled Content (FOUC) 之答疑解惑

FOUC的起源

FOUC现象在2001年首次被BlueRobot发现,并撰写了《Flash of Unstyled Content (FOUC)》一文。FOUC问题好像是对IE浏览器情有独钟。但是随后Dave Hyatt在2006年也发现Safari浏览器也存在同样的问题,并写下了《The FOUC Problem》一文。这两篇文章都显露出IE和Safari浏览器固有的异常的现象,无法对已经定义样式的内容进行渲染。

而最近又有一些迹象表明,当特定的JavaScript以及jQuery用于处理样式、图片、特别是网页内容时,如果页面加载后这些元素长时间无法加载或挂起,FOUC现象同样会发生。

FOUC产生的情况

  • 使用@import导入样式表
  • 将样式表放在页面底部而不是<head>内
  • 将多个样式表置于HTML文档的不同位置

FOUC现象的原理

当样式表晚于其要渲染的HTML元素加载时,等到加载此样式表后,浏览器就会重新渲染此页面,从而出现FOUC现象。

避免FOUC现象的方法

1、Brad Baxter最先在其文章《a FOUC tutorial by Brad Baxter》中概述了一种避免FOUC现象非常简单的方法:在包含所有或部分内容、id="fouc"的container通过js来添加一个"js"class名来隐藏这些内容,然后等所有样式和JS完全加载完毕后通过js将其display属性设置为"block",从而显示出内容。在Brad Baxter的例子中,他演示了使用建议的class和id名称​在<head>内添加的<style>和<script>标签,以及<body>内需要添加那些代码。

下面的截图演示了Brad Baxter处理FOUC所用的两页code片段:

Flash of Unstyled Content (FOUC) 之答疑解惑

2、John Polacek在《Help Prevent FOUC!》阐述了使用同样的技术避免FOUC的一种方法。他通过<style>和<script>标签,使用js方法将class名为"no-fouc"元素的display属性设置为none,这样直到页面完全被加载后相应的内容才会显示出来,代码可在GitHub Gist上下载。

Flash of Unstyled Content (FOUC) 之答疑解惑

3、Karl Swedberg在《1 Way To Avoid the Flash of Unstyled Content》使用了相似的技术来解决FOUC问题,他首先在<head>内设置要隐藏内容(class为"js")的样式,然后立即为html元素添加"js"class,在页面底部通过js显示,这样对不与支持js的用户就不会出现内容不显示的问题。他还提供了demo闪烁页面,在页面刚加载时列表是隐藏的,会出现闪烁现象。而在没有闪烁的demo页面Karl Swedberg将js放在页面的底部,FOUC现象几乎消失了。

<html>
  <head>
    <!-- etc. -->
    <style type="text/css">
      .js #flash {display: none;}
    </style>
    <script type="text/javascript">
      document.documentElement.className = 'js';
    </script>
  </head>
  <body>
    <!-- etc. -->
   
    <script type="text/javascript" src="/scripts/jquery.js"></script>
    <script type="text/javascript">
      // Stuff to do as soon as the body finishes loading.
      // No need for $(document).ready() here.
    </script>
  </body>
</html>

4、Paul Irish的博文《Avoiding the FOUC v3.0》同样引出了相同的方法。他的方法是添加"no-js"的class到标签,然后在<head>中用<script>添加js代码将"no-js"修改回为"js"。据Paul Irish所言,Modernizr也在<body>加载时使用此方法来设置元素的class。

<html class="no-js">
<head>
  <script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>

5、对于前端工程师而言,最简单的方法莫过于将css样式使用<link>置于<head>标签内。Steve Souders在其《14 Rules for Faster-Loading Web Sites》中的第5条规则中提到了这一点:Rule #5 – Put Stylesheets at the Top。其第5条规则表明将样式放在body最底部,紧靠</body>标签之前,就会出现FOUC现象,如下面的前后对比图所示:

Flash of Unstyled Content (FOUC) 之答疑解惑

本文采用CC BY-NC-ND协议进行许可,传播时请保留链接:http://huangzhiqun.com/skill/fouc.html

3,626 次阅读
  1. 目前还没有评论

发表评论

一 × = 三

注意: 评论者允许使用'@user空格'的方式将自己的评论通知另外评论者。例如, ABC是本文的评论者之一,则使用'@ABC '(不包括单引号)将会自动将您的评论发送给ABC。使用'@all ',将会将评论发送给之前所有其它评论者。请务必注意user必须和评论者名相匹配(大小写一致)。

疑惑 调皮 伤心 抠鼻 惊讶 微笑 脸红 坏笑 惊讶 发呆 撇嘴 酷 阴险 咒骂 愤怒 白眼 鼓掌 得意 汗 打呵欠 大哭 憨笑

评论