Eliminate flash of unstyled content

CssFouc

Css Problem Overview


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

Css Solutions


Solution 1 - Css

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.

Solution 2 - Css

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

Solution 3 - Css

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.

Solution 4 - Css

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>

Solution 5 - Css

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>

Solution 6 - Css

What I've done to avoid FOUC is:

  • Set the body section as: <body style="visibility: hidden;" onload="js_Load()">

  • Write a js_Load() JavaScript function: document.body.style.visibility='visible';

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.

Solution 7 - Css

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

Solution 8 - Css

Here is my code .. hope it solve your problem

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

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

Solution 9 - Css

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

Solution 10 - Css

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.

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

Solution 12 - Css

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>

Solution 13 - Css

The most simplest way I know of is to hide the html tag and then at the bottom of your javascript file, fade the html tag in.

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();

Source: https://gist.github.com/marchershey/139db0e8fd6f03a83578698409d333ce

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCMS CriticView Question on Stackoverflow
Solution 1 - CssStefanView Answer on Stackoverflow
Solution 2 - CssJeffView Answer on Stackoverflow
Solution 3 - CssAdam ZernerView Answer on Stackoverflow
Solution 4 - CssLawrence DolView Answer on Stackoverflow
Solution 5 - CssPaul CreamView Answer on Stackoverflow
Solution 6 - CssÁlvaro DuránView Answer on Stackoverflow
Solution 7 - CssdanideeView Answer on Stackoverflow
Solution 8 - CssCoding_snakeZView Answer on Stackoverflow
Solution 9 - CssJake BoomgaardenView Answer on Stackoverflow
Solution 10 - CssJochenView Answer on Stackoverflow
Solution 11 - CssNagibabaView Answer on Stackoverflow
Solution 12 - CssNazehsView Answer on Stackoverflow
Solution 13 - CssMarcView Answer on Stackoverflow