This post was previously updated on November 01, 2018.
We all have to deal with it at some point.
The Flash Of Unstyled Content. Yuck. What a name. According to TechRepublic it has its origins documented as far back as 2001. There are a wide range of fixes. This fix however is super duper easy to implement and it’s a vanilla solution.
First, add a class to your html document
<html class="no-js">...
Then put this little guy at the very-bottom of your scripts file:
(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)
And finally add this to your CSS, render content invisible until it loads:
visibility: hidden;
opacity: 0;
}
.js {
visibility: visible;
opacity: 1;
}
The obvious downside to this is pretty awful. If a user comes along that doesn’t have JS enabled, your page loads but it isn’t visible. It really comes down to a pros and cons list for your users. If you’re Facebook or Google, you probably have this baked into every single product because every single product uses JS in some small or large way.
I’m not saying this is the best solution ever — I’m just saying it’s the most effective solution we have right now. This method is a Frankenstein version of Paul Irish’s approach. Which if you’re going to use this FOUC solution you better be using Irish’s DOM Based JS Routing. Then you can really iron down when and where you want JS to fire.
UPDATE: Thanks to Bert, who reminded me that I haven’t written about FOUC solutions in some time, and happy to revisit the subject.
I do have a newly updated solution. It’s not much different than above but it’s more performant.
We continue to re-use Paul Irish’s famous markup from 2009, with only marginal updates. Such as, the no-js
class on the document, and script in the <head>
(not in the body, nor in the footer, this needs to be parsed right-away):
<html class="no-js">
<head>
<script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>
...
Next, we write CSS for the no-js
state:
.no-js {
visibility: hidden;
opacity: 0;
}
.js {
visibility: visible;
opacity: 1;
}
And Bob’s your uncle! Same as before, but only slightly revised for performance. Enjoy!
UPDATE: There’s more than one way to skin a cat as they say. Many thanks to elektrotype, who came up with this brilliant solution, which works great for no-js users. In-short, they won’t see a white-screen if they don’t have JS enabled:
10 responses
I read your article on avoiding FOUC. It seems a dangerous practice, to initially hide page content via CSS to everyone. As you point out, if JS is not enabled, nothing is displayed on the page.
So why not have the ‘visibility: hidden’ class of CSS assigned via vanilla JS in the head? Surely that way, if a page is loaded without JS enabled the ‘visibility: hidden’ class of CSS is never assigned and the page is loaded with some form of content.
I would really like to hear your opinion on this alternative approach and if that seems safer.
Kind regards,
Chris.
I think you’re totally onto something here!
Instead of assigning the
no-js
class tohtml
we setup the document with no class out-of-the-box and a stylesheet like this:Then we can assign the DOM a
loading
class with JS:Thoughts on this method?
Hi Stephen, I just came across this possible solution for the FOUC. I’m wondering if there has been any further development? I’m wanting to give this a try but want to know if you’ve tinkered any further.
Hey Bert! Thanks for reading. I’ve updated the solution above. Give it a whirl, let me know what you think. It’s more or less the same, but it still works like a charm.
Displaying a white page when javascript is disable is really an idea I dislike (a lot).
Here’s what work for me, no javascript required. I don’t know how this blog will parse HTML in comments so here’s a Gist.
Neat! Just gave it a try and works perfectly fine – without JS.
I just used this in top and tail style sheets in Gatsby and it works perfectly – thank you!
Once a style sheet is cached, though, this method is useless.
👆This.
terrible solution, wait, terrible idea, it solves nothing.
no js is no longer possible.