0

I'm trying to prevent FOUC in FF & IE. Loading my css async, (understandably) causes it. Setting a function to hide and then show the body works on Chrome, but not IE/FF.

I've tried every solution shown online, which are supposed to work and none have. Wondering if there is something being overlooked in my code; or another solution anyone knows?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">


    <title>Web Refinery</title>



    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">

    <style>
        .navbar.navbar-default.navbar-fixed-top{border:none;padding-right:2%;font-size:18px;background-color:#000;background-color:rgba(0,0,0,.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)}ul.navbar-left{color:#000;list-style: outside none none;padding-left:1%;padding-right:1%;margin-top:1%}a.navbar-brand{padding-top:1%;margin-bottom:1%;padding-right:1%}
    </style>



</head>
  <body style="display:none">
    <div class="container-fluid">
     <nav class="navbar navbar-default navbar-fixed-top">
          <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/"><img src="img/logo1-min.png"></a>     
          </div>

         <div class="collapse navbar-collapse" id="myNavbar">
            <ul class="navbar-left">
            <li type="none" class="hover descript">Design & Development</li> 
            </ul>  
            <ul class="nav navbar-nav navbar-right">
                <li class="hover"><a href="portfolio.html">Portfolio<span class="sr-only"></span></a></li>
                <li class="hover"><a href="services.html">Services</a></li>
            <li class="hover"><a href="contact.html">Contact<span class="sr-only"></span></a></li>
            </ul>
        </div><!-- /.navbar-collapse -->
      </nav>
      <div class="row text-center headDrop">
        <div class="col-md-1"></div>  
        <div class="col-md-10">
          <h1>WEB REFINERY</h1>
          <h2>Responsive Design & Development</h2>
        </div>
        <div class="col-md-1"></div>  
          <br>
        </div>  
        <div class="row text-center">
            <div class="col-md-1"></div>
            <div class="col-md-10">
                <br>

                <p>Metro Milwaukee - Design Studio</p>
                <p>Web Design - Development - Branding</p>
            </div>
            <div class="col-md-1"></div>
        </div>  
    </div>

        <script type="text/javascript">
        /* Beginning of async download code. */
        window.onload = function(){

            function loadjscssfile(filename, filetype) {
                if(filetype == "js") {
                    var cssNode = document.createElement('script');
                    cssNode.setAttribute("type", "text/javascript");
                    cssNode.setAttribute("src", filename);
                } else if(filetype == "css") {
                    var cssNode = document.createElement("link");
                    cssNode.setAttribute("rel", "stylesheet");
                    cssNode.setAttribute("type", "text/css");
                    cssNode.setAttribute("href", filename);
                }
                if(typeof cssNode != "undefined")
                    document.getElementsByTagName("head")[0].appendChild(cssNode);
            }
            loadjscssfile("//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css", "css");
            loadjscssfile("/css/main-min.css", "css");

            loadjscssfile("//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js", "js");
            loadjscssfile("//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js", "js");
            loadjscssfile("/js/main-min.js", "js");



        };
        /* End of async download code. */

        document.onreadystatechange = function () {
                var view = document.getElementsByTagName('body')[0];
                  if (document.readyState == "complete") {
                      view.style.removeProperty('display');
                  } else {}

        };


    </script>   

  </body>

</html>
  • Not an entirely on-topic question, is there a reason you load your styles and scripts like that and not simply loading them by declaring the `` and ` – Tasos K. Nov 07 '15 at 20:57
  • Hi Tasos - Modern performance optimizations standards suggest loading files asynchronously. Currently my site is loading the CSS synchronously (just declaring the tags in the ) and loading the JS files async. However, when I load both –  Nov 07 '15 at 23:19
  • You probably shouldn't load CSS async. If there is no CSS, there are no styles to be rendered, thus FOUC. You could however hide the contents of the page via CSS in the head and only show it when the CSS has been loaded. But I think I would just load the CSS synchronously (unless you have more than a few 100K of it). – nils Nov 07 '15 at 23:38
  • `Setting a function to hide and then show the body works on Chrome, but not IE/FF.` - you **must** be doing it wrong then. removing `display:none` when `document.readyState == 'complete'` will do so before any of your asynch styles are loaded. I'm surprised it works in Chrome, but then chrome does have it's quirks with these types of events – Jaromanda X Nov 08 '15 at 05:38

3 Answers3

2

Heres the solution I use to solve FOUC problems. I set the opacity of the HTML tag to 0 and give the template .25 seconds to finish pulling down all the CSS templates it needs. Then use JQuery to fade in the content.

<html id="no-fouc" lang="en">

<style type="text/css">
        #no-fouc { opacity: 0; }
</style>

Add this bit to the very bottom of your script just before the closing body tag.

$("#no-fouc").delay(250).animate({"opacity": "1"}, 250);

Works in all browsers and media I've tested and appears to fix a problem with Google PageSpeed too. They don't like it if you do things like set display:none so this was the closest thing I could come up with.

Vince
  • 910
  • 2
  • 13
  • 29
1

I upvoted your Answer @Vince, but I wanted to show you an approach without using any javascript:

<html id="no-fouc" lang="en" class="no-js">

<head>
<style type="text/css">
@-webkit-keyframes fadeIn {
    0% { opacity: 0; }
    20% { opacity: 0; }
    40% { opacity: 0.3; }
    60% { opacity: 0.5; }
    80% { opacity: 0.9; }
    100% { opacity: 1; }
}

#no-fouc {
    opacity: 0;
   -webkit-animation-name: fadeIn;
   -webkit-animation-duration: 1s;
   animation-iteration-count: 1;
   animation-name: fadeIn;
   animation-duration: 1s;
   // This line forces the browser to set the opacity to 1 after executing/finishing the animation
   opacity: 1;

}

// include your stylesheets here, if you want you can set the opacity afterwards to 1 which I would recommend if you are using external stylesheets

</head>
...

</html>

Shoutout to the answers on the topic Animation CSS3: display + opacity on stack overflow

JasParkety
  • 131
  • 1
  • 6
0

I would remove the display:none style once all the CSS has finished loading, like this

window.onload = function(){
    var resources = [
        { url: "//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css", type: "css"},
        { url: "/css/main-min.css", type: "css"},

        { url: "//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js", type: "js"},
        { url: "//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js", type: "js"},
        { url: "/js/main-min.js", type: "js"}
    ];
    var head = document.getElementsByTagName("head")[0];
    var cssToLoad = 0;
    var loadOrError = function (e) {
        cssToLoad -= 1;
        if (cssToLoad < 0) { // prevent early trigger
            document.body.style.removeProperty('display');
        }
    };
    resource.forEach(function(resource) {
        var element;

        if (resource.type == "js") {
            element = document.createElement('script');
            element.setAttribute("type", "text/javascript");
            element.setAttribute("src", resource.url);
        } else if (resource.type == "css") {
            cssToLoad += 1;
            element = document.createElement("link");
            element.setAttribute("rel", "stylesheet");
            element.setAttribute("type", "text/css");
            element.setAttribute("href", resource.url);
            element.addEventListener('load', loadOrError);
            element.addEventListener('error', loadOrError);
        }
        if (typeof element != "undefined") {
            head.appendChild(element);
        }
    });
    loadOrError(); // end prevent early trigger
};
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • Awesome! Thanks Jaromanda! All excellent information and very informative :) –  Nov 08 '15 at 18:00