消除无样式内容的闪烁

发布于 2024-09-08 19:28:56 字数 29 浏览 4 评论 0 原文

如何停止网页上出现无样式内容 (FOUC)?

How do I stop the flash of unstyled content (FOUC) on a web page?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

〆一缕阳光ご 2024-09-15 19:28:56

使用 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'))方法的*外部*调用的。

The problem with using a css style to initially hide some page elements, and then using javascript to change the style back to visible after page load, is that people who don't have javascript enabled will never get to see those elements. So it's a solution which does not degrade gracefully.

A better way therefore, is to use javascript to both initially hide as well as redisplay those elements after page load. Using jQuery, we might be tempted to do something like this:

$(document).ready(function() {
    $('body').hide();
    $(window).on('load', function() {
        $('body').show();
    });
});

However, if your page is very big with a lot of elements, then this code won't be applied soon enough (the document body won't be ready soon enough) and you might still see a FOUC. However, there is one element that we CAN hide as soon as script is encountered in the head, even before the document is ready: the HTML tag. So we could do something like this:

<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>

Note that the jQuery addClass() method is called *outside* of the .ready() (or better, .on('load')) method.

深陷 2024-09-15 19:28:56

这是对我有用的,不需要 javascript,它非常适合包含许多元素和大量 css 的页面:

首先,为 添加专用的

<!doctype html>
<html>
<head>
    <style>html{visibility: hidden;opacity:0;}</style>

然后,在最后一个 .css 样式表文件的末尾,将可见性和不透明度样式设置为“可见”和“1”,分别:

html {
    visibility: visible;
    opacity: 1;
}

如果您已经有“html”标签的现有样式块,则将整个“html”样式移动到最后一个 .css 文件的末尾,并添加“visibility”和“opacity”标签,如上所述。

https://gist.github.com/ electrotype/7960ddcc44bc4aea07a35603d1c41cb0

This is the one that has worked for me and does not require javascript and it works great for pages with many elements and lots of css:

First, add a dedicated <STYLE> setting for the <HTML> tag with visibility 'hidden' and opacity as '0' at the top of your HTML, e.g, in the beginning of the <HEAD> element, for example, at the top of your HTML add:

<!doctype html>
<html>
<head>
    <style>html{visibility: hidden;opacity:0;}</style>

Then, at the end of your last .css stylesheet file, set the visibility and opacity styles to 'visible' and '1', respectively:

html {
    visibility: visible;
    opacity: 1;
}

If you already have an existing style block for the 'html' tag, then move the entire 'html' style to the end of the last .css file and add the 'visibility' and 'opacity' tags as described above.

https://gist.github.com/electrotype/7960ddcc44bc4aea07a35603d1c41cb0

萌︼了一个春 2024-09-15 19:28:56

仅 CSS 解决方案:

<html>
  <head>
    <style>
      html {
        display: none;
      }
    </style>
    ...
  </head>
  <body>
    ...
    <link rel="stylesheet" href="app.css"> <!-- should set html { display: block; } -->
  </body>
</html>

当浏览器解析 HTML 文件时:

  • 它要做的第一件事是隐藏
  • 它要做的最后一件事是加载样式,然后显示应用了样式的所有内容。

与使用 JavaScript 的解决方案相比,此解决方案的优势在于,即使用户禁用了 JavaScript,它也能正常工作。

注意:您允许 放入 内部。但我确实认为这是一个缺点,因为它违反了惯例。如果有 defer 的 > 属性与

A CSS-only solution:

<html>
  <head>
    <style>
      html {
        display: none;
      }
    </style>
    ...
  </head>
  <body>
    ...
    <link rel="stylesheet" href="app.css"> <!-- should set html { display: block; } -->
  </body>
</html>

As the browser parses through the HTML file:

  • The first thing it will do is hide <html>.
  • The last thing it will do is load the styles, and then display all the content with styling applied.

The advantage to this over a solution that uses JavaScript is that it will work for users even if they have JavaScript disabled.

Note: you are allowed to put <link> inside of <body>. I do see it as a downside though, because it violates common practice. It would be nice if there was a defer attribute for <link> like there is for <script>, because that would allow us to put it in the <head> and still accomplish our goal.

自在安然 2024-09-15 19:28:56

一个不依赖于 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>

A solution which doesn't depend on jQuery, which will work on all current browsers and do nothing on old browsers, include the following in your head tag:

<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>

Thanks to @justastudent, I tried just setting elm.style.display="none"; and it appears to work as desired, at least in current Firefox Quantum. So here is a more compact solution, being, so far, the simplest thing I've found that works.

<script type="text/javascript">
    var elm=document.getElementsByTagName("html")[0];
    elm.style.display="none";
    document.addEventListener("DOMContentLoaded",function(event) { elm.style.display="block"; });
</script>
慕烟庭风 2024-09-15 19:28:56

另一个在 Firefox Quantum 中也有效的快速修复是 中的空

我100%成功了。我认为这也是为什么上述解决方案与其他 JS 一起工作的主要原因。

<script type="text/javascript">

</script>

An other quick fix which also works in Firefox Quantum is an empty <script> tag in the <head>. This however, penalizes your pagespeed insights and overall load time.

I had 100% success with it. I think it's also the main reason, why above solutions with other JS in the works.

<script type="text/javascript">

</script>
小姐丶请自重 2024-09-15 19:28:56

这里介绍的纯 CSS 解决方案都不适用于现代浏览器(CSS 和字体的异步加载)。你必须使用 JavaScript。我为避免 FOUC 所做的事情是:

<html>
  <body onload="document.body.style.visibility=`visible`;">
    <script>document.body.style.visibility=`hidden`;</script>

通过这种方法,我的网页正文将保持隐藏,直到加载完整页面和 CSS 文件。一旦所有内容都加载完毕,onload 事件就会使主体可见。因此,网络浏览器保持为空,直到所有内容都弹出在屏幕上。

这是一个简单的解决方案,但到目前为止它是有效的。

这不会影响已禁用 Javascript 的用户,因为

None of the CSS-only solutions presented here work with modern browsers (asynchronous loading of css and fonts). You have to use Javascript. What I've done to avoid FOUC is:

<html>
  <body onload="document.body.style.visibility=`visible`;">
    <script>document.body.style.visibility=`hidden`;</script>

With this approach the body of my web page is kept hidden until the full page and CSS files are loaded. Once everything is loaded, the onload event turns the body visible. So, the web browser remains empty until a point when everything pops up on the screen.

It is a simple solution but so far it is working.

This will not affect users who have disabled Javascript because the <script> tag is ignored.

迷离° 2024-09-15 19:28:56

此页面上的每个答案都会减慢加载速度,并且只会隐藏根本问题。如果您遇到 FOUC,请找出发生这种情况的原因并解决它。

从本质上讲,这种情况正在发生:

  • 因为您的样式表未正确加载:它们应该通过 HTML 中的 link 标记加载,而不是通过 JavaScript,
  • 因为您放置了 script 标记在 link 标记之前,这可能会强制执行“布局操作”,并在浏览器尝试加载样式之前欺骗浏览器进行渲染。

作为参考,以下是 FOUC 的示例:

FOUC 示例

Every answer on this page slows down the load and it only hides the underlying issue. If you're experiencing FOUC, find out WHY it's happening and fix that.

At the core, this is happening:

  • because your stylesheets are not being loaded correctly: they should be loaded via link tag in the HTML, not via JavaScript
  • because you placed script tags before link tags, which may force a "layout operation" and trick the browser into rendering before it even attempts to load the style.

For reference, here's an example of FOUC:

FOUC example

就此别过 2024-09-15 19:28:56

没有人谈论过 CSS @import

这对我来说就是问题,我使用 @import 直接在我的 css 文件中加载两个额外的样式表

简单的解决方案:替换所有 @import 链接

No one has talked about CSS @import

That was the problem for me i was loading two extra style sheets directly in my css file with @import

Simple solution: Replace all @import links with <link />

红颜悴 2024-09-15 19:28:56

一个简单的解决方案可以避免在没有 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>

当解析器到达正文时,它会使用“opacity: 0”淡出。当解析器在解析其他所有内容后最终到达最底部时,正文会使用页内样式再次淡入。 !important 关键字很重要;-),因为它推翻了 body 标记之前的内联样式。

在这种情况下,使用“opacity: 0”淡出比“display: none”更好,因为如果您通过 javascript 完成布局操作,那么当受影响的元素未渲染时,它们可能不起作用。

这对我有用。

A simple solution to avoid a flash of unstyled content without 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>

When the parser arrives at the body, it is faded out using "opacity: 0". When the parser finally arrives at the very bottom after everything else is parsed, the body is faded in again using an in-page style. The !important keyword there is important ;-), because it overrules the previous inline style of the body tag.

In this case, using "opacity: 0" to fade out is better than "display: none", because if you have layout operations done by javascript, they may not work when the affected element is not rendered.

That worked for me.

待天淡蓝洁白时 2024-09-15 19:28:56

我想出了一种不需要任何实际代码更改的方法,哇哦!我的问题与在一些 javascript 文件之后导入几个 css 文件有关。

为了解决这个问题,我刚刚移动了我的 CSS 链接,以便它们位于我的 javascript 导入之上。这使得我的所有 CSS 都可以导入并准备好尽快运行,这样当 HTML 出现在屏幕上时,即使 JS 还没有准备好,页面也会被正确格式化

I came up with a way that requires no real code change whatsoever, woohoo! My issue was related to importing several css files AFTER some javascript files.

To resolve the issue I just moved my CSS links so that they would be above my javascript imports. This allowed all my CSS to be imported and ready to go ASAP, so that when the HTML appears on the screen, even if the JS isn't ready, the page will be properly formatted

傲影 2024-09-15 19:28:56

这是我的代码..希望它能解决您的问题

设置

<script>
    $(document).ready(function() {
        $("body").css('opacity', 1);
    });
</script>

Here is my code .. hope it solve your problem

set <body style="opacity:0;">

<script>
    $(document).ready(function() {
        $("body").css('opacity', 1);
    });
</script>
拥有 2024-09-15 19:28:56

到目前为止我发现的最佳解决方案是这样的:

  1. 将标题的所有样式添加到 中的

  2. 在样式标记添加顶部.not-visible-first{visibility: hide} + 其他标题样式

  3. 在 body 末尾通过 JS 添加 css

    document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeend","");

  4. 并记住添加 .not-visible-first{visibility:visibility}main.min.css

    的末尾,

此选项将创造更好的用户体验

The best solution I found till now is like this:

  1. Add all styles of your header to a <style/> tag in <head/>

  2. at the top of style tag add .not-visible-first{visibility: hidden} + other header style

  3. Add css via JS at the end of body

    document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeend","<link rel=\"stylesheet\" href=\"/css/main.min.css?v=1.2.4338\" />");

  4. And remember to add .not-visible-first{visibility: visible} to the end of main.min.css

This option will create better user experience

蝶舞 2024-09-15 19:28:56

你可以用香草试试这个

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>

You could try this with vanilla

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>

孤蝉 2024-09-15 19:28:56

对我来说,在 FireFox 上修复 FOUC 很简单,只需更改我的 中的 css 链接代码即可:

<link rel="stylesheet" href="/assets/main.css">

...为此:

<link rel="stylesheet" type="text/css" href="/assets/main.css" />

我相信包括 type="text/css “ 帮助 FireFox 优先考虑 CSS 加载和渲染?这就是我的看法。干杯!

For me, fixing FOUC on FireFox was easy as changing the css linking code in my <head> from this:

<link rel="stylesheet" href="/assets/main.css">

...To this:

<link rel="stylesheet" type="text/css" href="/assets/main.css" />

I believe including the type="text/css" helps FireFox prioritize CSS loading and rendering? That's my take. Cheers!

街道布景 2024-09-15 19:28:56

自从提出这个问题以来,十三年来发生了很大的变化。现代企业软件的内容安全策略不允许内联样式、内联样式标签或内联脚本标签。向单页应用程序的发展已将 FOUC 的问题从文档正文扩展到其他容器元素。我发现处理这个问题的最优雅和最强大的方法就是使用隐藏属性。

<section class="my-section" hidden>

此属性将正文或任何其他标记的 CSS 显示值默认为“none”。与该标记块对应的 CSS 文件只需具有相关容器元素所需的显示值。很多时候,情况已经如此,因此不需要额外的 CSS。仅当相应的 CSS 加载后,内容才会显示。

/* Corresponding CSS File */

.my-section {
   display: flex; /* or any other desired value */
}

Much has changed in the thirteen years since this question was asked. Content security policies for modern enterprise software do not allow inline styles, inline style tags, or inline script tags. The move toward single page applications has extended the problem of FOUCs from just the document body to other container elements. The most elegant and powerful way I've found to deal with this problem is simply to use the hidden attribute.

<section class="my-section" hidden>

This attribute defaults the body or any other tag to a CSS display value of "none". Your CSS file corresponding to that block of markup need only have a desired display value for the container element in question. Quite often, this is already the case, so no additional CSS is required. The content will only show once the corresponding CSS loads.

/* Corresponding CSS File */

.my-section {
   display: flex; /* or any other desired value */
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文