页面加载时闪烁

21
在一个网站上,我在页面加载之间经历了一个白屏的“闪烁”。由于使用的是背景图像,所以当页面加载时,背景图像会在出现在屏幕上之前“闪烁”(请自行查看)。这个问题在Chrome和IE中都存在,但在Firefox中不存在。
该网站有一种预加载内容的方法。页面上的每个元素都位于一个名为#website的DIV包装器中,最初处于display:none的状态,每个图像都位于一个名为#website-images的DIV包装器中,该包装器也被隐藏。然后,该网站(使用jQuery插件)检查#website-images中的所有图像是否已经加载完毕,一旦加载完毕,就会设置一个cookie来记住此用户已经加载过图像,因此不会再次进行预加载处理并展示网页的调用$("#website").show()
那么,是什么导致了页面加载之间的闪烁?是我的预加载图像的方式吗?我已经添加了不同的文档类型,并更改了元信息,但什么都没有起作用。我真的很迷茫,有人有想法或见解吗?

我真正想做的是在IMG完全加载之前不渲染页面,然后再渲染整个页面。如果我将body样式设置为display:none,并在body末尾放置JavaScript以将body样式设置回block,仍然会出现白色闪烁,在Firefox和Chrome中都是如此。我认为实际上img的加载是在整个页面被渲染之后完成的?似乎不可能消除这种白色闪烁;奇怪。 - David Spector
4个回答

53

出现这种情况是因为DOMLoaded事件在页面实际渲染之前几毫秒被触发。

简而言之,这意味着您必须优化网站的速度。这并不意味着使其下载速度更快,而是以正确的顺序、以非阻塞方式下载。

第一步:您的标记

1) 看起来您可以做很多事情来优化您的标记。首先,样式表和JavaScript文件的顺序可以进行优化。为了确保CSS文件异步下载,您必须始终在外部JavaScript文件之前包含外部CSS。style.css在一些/全部JavaScript调用后下载。

在head中找到了1个脚本块,位于外部CSS文件和另一个资源之间。为了允许并行下载,请将内联脚本移到外部CSS文件之前或下一个资源之后。

2) 您的主JavaScript文件是内联在您的标记中的。这不仅会阻止页面下载,直到脚本完成下载,还会导致(或增加)白色闪烁,因为它在您的内容之前。

我推荐在head中异步加载您的脚本。然后,您将不得不在DOM完成加载时触发脚本,或者可以通过将脚本放在body标记底部来实现相同的结果。

第二步:利用浏览器的功能

1) 查看http头时,发现有28个项目被作为单独的HTTP调用提供,这些项目在浏览器上没有被缓存(包括html页面、jpg图像、样式表和JavaScript文件)。

这些项目明确是不可缓存的,通过编辑您的Web服务器配置很容易解决。

2) 启用gzip压缩。大多数web浏览器(包括IE)都支持gzip解压缩,大多数(如果不是全部)web服务器都支持使用gzip压缩。您甚至可以过度使用,并查看SPDY,这是一种替代较轻的HTTP协议(受Chrome和Firefox支持)。

第三步:内容服务

您的域名有大约30个单独的项目正在提供服务。首先,考虑如何减少此请求数量。每个页面视图的30个HTTP请求是很多的。您可以使用以下方法来解决这个问题:

1)在多个主机名之间进行并行下载。浏览器目前限制了对单个域的并发连接数。从不同的域(例如img.bigtim.ca)提供图像可以使它们与其他内容一起并行提供。

2)将多个项目合并为一个。许多被下载的项目仅是样式内容,例如标志、菜单元素等。这些可以组合成一个单一的图像(仅下载一次),并使用CSS进行分割。这称为CSS精灵技术。Stack Overflow就是这样做的:请看这里

3)如果无法减少需要下载的项目数量,可以通过从一个无cookie的域中提供静态内容来减轻服务器负载(从而减轻客户端浏览器的负载)。Stack Overflow对其所有静态内容(例如图像、样式表和脚本)都使用此方法。

第四步:优化自己的代码

HTTP和浏览器技术能为您的网站速度提供帮助的空间有限。这最后一步取决于您自己。

1)您是否有什么理由选择自己托管jquery?Jquery下载页面显示了多个CDN,您可以指向这些CDN以获取速度快、缓存的脚本下载。

2)目前在您的样式表中有超过20个未使用的CSS规则(占用了整个CSS文件的36%)。重新考虑一下到底需要什么。

3)主要的JavaScript代码块(位于body标签的顶部)似乎是一个尝试加速的hack,但可能没有起到任何作用。

设置了一个cookie来指定页面是否已经淡出。您不仅在使用JavaScript执行可以轻松通过CSS执行的转换,而且超过一半的脚本用于定义读写cookie的功能。

看到像这样的代码:$("body").css ("background-image", "url('images/background.png')");$("#website").show ();,通常让我开始对“关注点分离”发表评论,但此答案已经足够长了,希望您能看出在同一段代码中混合样式和功能是不好的实践。

补充说明:查看代码,根本没有必要使用jquery来执行你正在做的事情。但话又说回来,也没有必要执行你正在做的事情,所以您可能完全可以不使用JavaScript来做得更好。


1
Greg,你对“新”的前端JS框架中的关注点分离有何感想? - johnny
1
@johnny 一言以蔽之:糟糕透顶。我们已经学了几十年将 HTML、JS 和 CSS 分离的好处,但新的框架不断出现,却毫不留情地破坏着网络,而且没有任何补救措施。 - Greg
你会选择继续使用jQuery还是直接使用JS或两者兼备? - johnny
1
@johnny 这要看情况。我喜欢尽可能将逻辑保留在服务器端,所以现在我很少使用 JavaScript,而 jQuery 则有些过度。不过,如果你需要大量使用 JavaScript,它提供的跨浏览器 API 仍然是非常有用的。 - Greg

8
把 JavaScript 移到 HTML 结束前的 body 标签前面,有时会有所帮助。

1
CSS是渲染阻塞的。将CSS分为两部分 -
  • 关键CSS
  • 非关键CSS

使关键CSS随页面一起加载。它应该嵌入在head标签中。 通过ajax进行非关键CSS的延迟加载。

这将导致网页严重优化,减少空白屏幕时间。

此外,您可以考虑以异步/延迟的方式加载JavaScript。


1

我知道这是一个旧的帖子,但是我尝试并且有效的一个技巧。

这个想法是在CSS完全加载时不显示任何内容。

在HTML文件中:

<body style="display:none">

在你的CSS中,最后一行:

body{display:block !important}

对我来说,这没有任何影响。在渲染4.5MB的IMG元素之前,仍然会出现大的白色闪光。我使用的是STYLE标签,而不是外部CSS,因为我正在使用Bootstrap 5。 - David Spector

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接