消除无样式内容的闪烁
Posted
技术标签:
【中文标题】消除无样式内容的闪烁【英文标题】:Eliminate flash of unstyled content 【发布时间】:2011-03-14 09:19:29 【问题描述】:如何阻止网页上无样式内容 (FOUC) 的闪烁?
【问题讨论】:
如果我们在网页底部引用了样式表的链接标签,这种情况会发生很多次。 【参考方案1】:在没有 javascript 的情况下避免出现无样式内容的简单解决方案:
<!DOCTYPE html>
<html>
<head>
<title>Bla bla</title>
<link href="..." rel="stylesheet" />
<link href="..." rel="stylesheet" />
</head>
<body style="opacity: 0">
<!-- All HTML content here -->
<script src="..."></script>
<script src="..."></script>
<style>
body
opacity: 1 !important;
</style>
</body>
</html>
当解析器到达 body 时,它使用“opacity: 0”淡出。当解析器在解析完其他所有内容后最终到达最底部时,使用页内样式再次淡入正文。 !important 关键字很重要 ;-),因为它覆盖了 body 标记的先前内联样式。
在这种情况下,使用“opacity: 0”淡出比“display:none”更好,因为如果你有通过javascript完成的布局操作,当受影响的元素没有渲染时它们可能不起作用。
这对我有用。
【讨论】:
【参考方案2】:我所知道的最简单的方法是隐藏 html 标记,然后在 javascript 文件的底部,淡入 html 标记。
HTML
<html style="display:none;">
...
</html>
Javascript
/*
* FOUC Fix - Flash of Unstyled Content
* By default, the <html> tag is hidden to prevent the flash of unstyled content.
* This simple fadeIn() function will allow the page to gracefully fade in once
* all assets are loaded. This line of code must remain at the bottom of the js
* assets.
*/
$( 'html' ).fadeIn();
来源:https://gist.github.com/marchershey/139db0e8fd6f03a83578698409d333ce
【讨论】:
请注意,fadeIn()
是一个 jQuery 方法,而不是原生 JavaScript。【参考方案3】:
你可以用香草试试这个
function js_method()
//todos
var elementDiv = document.getElementById("main");
elementDiv.style.display ="block";
<body onload="js_method()" id="main" style="display:none">
//todos
<h2>Hello</h2>
</body>
【讨论】:
【参考方案4】:这是我的代码..希望它能解决你的问题
set <body style="opacity:0;">
<script>
$(document).ready(function()
$("body").css('opacity', 1);
);
</script>
【讨论】:
令人惊讶的是,在许多无法阻止 FOUC 的 sn-ps 中——这个确实有效——对我来说。请注意,正文样式上缺少“结尾”,应为<body style="opacity:0;">
【参考方案5】:
到目前为止我找到的最佳解决方案是这样的:
将标题的所有样式添加到<head/>
中的<style/>
标记
在样式标签顶部添加.not-visible-firstvisibility: hidden
+ 其他标题样式
在body末尾通过JS添加css
document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeend","<link rel=\"stylesheet\" href=\"/css/main.min.css?v=1.2.4338\" />");
记得在main.min.css
末尾加上.not-visible-firstvisibility: visible
此选项将创造更好的用户体验
【讨论】:
【参考方案6】:我想出了一种不需要任何实际代码更改的方法,哇哦!我的问题与在一些 javascript 文件之后导入几个 css 文件有关。
为了解决这个问题,我刚刚移动了我的 CSS 链接,以便它们位于我的 javascript 导入之上。这使得我所有的 CSS 都可以被导入并尽快准备好,这样当 HTML 出现在屏幕上时,即使 JS 还没有准备好,页面也会被正确格式化
【讨论】:
【参考方案7】:这是对我有用的,不需要 javascript,它适用于包含许多元素和大量 css 的页面:
首先,为<HTML>
标记添加一个专用的<STYLE>
设置,在HTML 顶部,例如<HEAD>
元素的开头,可见性为“隐藏”,不透明度为“0” , 在 HTML 的顶部添加:
<!doctype html>
<html>
<head>
<style>htmlvisibility: hidden;opacity:0;</style>
然后,在最后一个 .css 样式表文件的末尾,将可见性和不透明度样式分别设置为“可见”和“1”:
html
visibility: visible;
opacity: 1;
如果您已经有一个现有的 'html' 标记样式块,则将整个 'html' 样式移动到最后一个 .css 文件的末尾,并如上所述添加 'visibility' 和 'opacity' 标记。
https://gist.github.com/electrotype/7960ddcc44bc4aea07a35603d1c41cb0
【讨论】:
这确实应该是公认的正确答案。如果 JS 被禁用或出现 JS 错误,则不显示任何页面是一个坏主意,这更容易访问。 @Jeff,非常感谢您提供此解决方案!解决了我的问题! 这也不会干扰禁用 CSS 的浏览器(例如,互联网访问速度慢或有残疾的浏览器可能会选择禁用图像、Javascript 和 CSS)。 Opera 可能是最著名的浏览器示例,它曾经在主工具栏上有一个按钮来关闭 CSS。这种方法的缺点是如果 CSS 文件加载失败,页面将是空白的。例如,将您的 CSS 文件命名为“ads.css”将触发广告拦截器插件,并且文件将无法加载,从而使页面完全空白。 (当然,这可能是故意的......) 这是我最喜欢使用的技术;但是,我发现我需要在样式表中的head
和htmldisplay:block;
中使用htmldisplay:none;
,才能使用基于Chromium 的浏览器完全征服FOUC。 (我在body
上设置的深色背景没有遇到过问题。)
这个解决方案与一年多前 Adam Zerner 的解决方案几乎没有区别。【参考方案8】:
另一个同样适用于 Firefox Quantum 的快速修复是 <head>
中的空 <script>
标签。但是,这会损害您的页面速度洞察力和整体加载时间。
我取得了 100% 的成功。我认为这也是主要原因,为什么上述解决方案与其他 JS 在工作中。
<script type="text/javascript">
</script>
【讨论】:
即使完全不可靠也超级有趣【参考方案9】:一个不依赖于 jQuery 的解决方案,它适用于所有当前的浏览器,并且在旧浏览器上什么也不做,在你的 head 标签中包含以下内容:
<head>
...
<style type="text/css">
.fouc-fix display:none;
</style>
<script type="text/javascript">
try
var elm=document.getElementsByTagName("html")[0];
var old=elm.class || "";
elm.class=old+" fouc-fix";
document.addEventListener("DOMContentLoaded",function(event)
elm.class=old;
);
catch(thr)
</script>
</head>
感谢@justastudent,我尝试设置elm.style.display="none";
,它似乎可以正常工作,至少在当前的Firefox Quantum 中是这样。所以这是一个更紧凑的解决方案,到目前为止,它是我发现的最简单的方法。
<script type="text/javascript">
var elm=document.getElementsByTagName("html")[0];
elm.style.display="none";
document.addEventListener("DOMContentLoaded",function(event) elm.style.display="block"; );
</script>
【讨论】:
上述代码对我不起作用,这是我的版本:try var html=document.getElementsByTagName("html")[0]; document.addEventListener("DOMContentLoaded", function(event) html.className=''; ); html.className='fouc'; 捕捉(错误) 我喜欢这种方法,但建议使用classList
API。
其实,为什么一开始就使用单独的 CSS 呢?为什么不做elm.style.display = 'none';
然后用elm.style.removeProperty('display');
撤消呢?
@Justastudent :因为在禁用 Javascript 的情况下会显示一个空白页面。
@Justastudent:谢谢。我试过了,它至少在当前的浏览器中有效。答案增强。【参考方案10】:
没有人谈论过 CSS @import
这对我来说是个问题,我用@import
直接在我的css文件中加载了两个额外的样式表
简单的解决方案:将所有@import
链接替换为<link />
【讨论】:
这发生在我身上。我希望将来@import
会是同步的。【参考方案11】:
纯 CSS 解决方案:
<html>
<head>
<style>
html
display: none;
</style>
...
</head>
<body>
...
<link rel="stylesheet" href="app.css"> <!-- should set html display: block; -->
</body>
</html>
当浏览器解析 HTML 文件时:
它首先会隐藏<html>
。
它要做的最后一件事是加载样式,然后显示应用了样式的所有内容。
与使用 JavaScript 的解决方案相比,这样做的优势在于,即使用户禁用了 JavaScript,它也能正常工作。
注意:你是allowed 把<link>
放在<body>
里面。不过,我确实认为这是一个缺点,因为它违反了惯例。如果<link>
有一个defer
属性就好了,就像<script>
一样,因为这样我们就可以把它放在<head>
中并且仍然实现我们的目标。
【讨论】:
知道display: none
也将隐藏背景图像或颜色很有用。由于我的网站有一个深色主题,它会闪烁白色。使用visibility: hidden
更适合我的情况。
即使对样式表的引用位于 <head>
而不是 <body>
中,此解决方案也将起作用。 (虽然我想如果你有一个很长的页面,浏览器可能会在页面末尾加载之前开始显示页面。但是,这实际上是我的首选行为,因为我的网站正在从数据库中加载大表)。为不需要 JavaScript 的简单解决方案点赞!【参考方案12】:
使用 css 样式最初隐藏某些页面元素,然后在页面加载后使用 javascript 将样式更改回可见的问题在于,未启用 javascript 的人将永远无法看到这些元素。所以这是一个不会优雅降级的解决方案。
因此,更好的方法是使用 javascript 在页面加载后开始隐藏和重新显示这些元素。使用 jQuery,我们可能会做这样的事情:
$(document).ready(function()
$('body').hide();
$(window).on('load', function()
$('body').show();
);
);
但是,如果您的页面非常大,包含很多元素,那么此代码将不会很快应用(文档正文不会很快准备好),您可能仍会看到 FOUC。但是,一旦在头部遇到脚本,甚至在文档准备好之前,我们就可以隐藏一个元素:HTML 标记。所以我们可以这样做:
<html>
<head>
<!-- Other stuff like title and meta tags go here -->
<style type="text/css">
.hidden display:none;
</style>
<script type="text/javascript" src="/scripts/jquery.js"></script>
<script type="text/javascript">
$('html').addClass('hidden');
$(document).ready(function() // EDIT: From Adam Zerner's comment below: Rather use load: $(window).on('load', function () ...);
$('html').show(); // EDIT: Can also use $('html').removeClass('hidden');
);
</script>
</head>
<body>
<!-- Body Content -->
</body>
</html>
请注意,jQuery addClass() 方法是在 .ready() (或更好的 .on('load'))方法之外调用的。
【讨论】:
对我来说,将$('html').show()'
替换为$('html').removeClass('hidden');
似乎更简洁。这更清楚地表明,就绪函数正在撤消addClass
。
更新:刚刚测试了这种方法。当前版本的 jQuery 要求使用 removeClass
(正如我建议的那样)而不是 show
(如原始答案中的那样)来完成 - 否则 html 将永远不会显示。我相信 jQuery 的 show() 现在显式地从 css 样式中查找并恢复任何显示状态,以避免干扰样式。因此,有必要实际删除“隐藏”类。
完美运行。选择了 removeClass 选项而不是 show()
纯 CSS 解决方案怎么样,在 <head>
中有 <style>html display: none; </style>
,然后在 </body>
之前有真正的样式?
我们不应该寻找加载事件而不是准备好吗?通过加载,我们知道 CSS 将准备就绪。准备好后,我们不知道 CSS 会准备好。【参考方案13】:
我为避免 FOUC 所做的事情是:
设置正文部分为:<body style="visibility: hidden;" onload="js_Load()">
写一个js_Load()
JavaScript 函数:document.body.style.visibility='visible';
使用这种方法,我的网页正文会一直隐藏,直到整个页面和 CSS 文件加载完毕。加载完所有内容后,onload 事件会使主体可见。因此,网络浏览器一直是空的,直到屏幕上弹出所有内容。
这是一个简单的解决方案,但到目前为止它正在工作。
【讨论】:
如果查看者没有启用 javascript,那就不好了,因为那样他们就什么也看不到了。 -1 用于建议一个解决方案,该解决方案将向未启用 javascript 或使用不支持 javascript 的屏幕阅读器或位于阻止的公司防火墙后面的用户显示任何内容javascript。谷歌搜索“消除不需要的内容的闪光”将显示许多不存在此缺陷的方法。例如,Stefan 的答案(一年后)要安全得多。 你真的应该在最后添加<noscript><style>body visibility: visible; </style></noscript>
,这样网站也可以在禁用 JS 的情况下工作。
企业防火墙阻止 Javascript?换公司的理由...
以下来自 Jeff 的答案是我认为的正确答案。它不依赖于 javascript,并且更易于访问。以上是关于消除无样式内容的闪烁的主要内容,如果未能解决你的问题,请参考以下文章