Prevent Flash Of Unstyled Content (FOUC)

I’ve used a masonry library, and layed out a page using JavaScript

But, every now and then I get a flash of unstyled content for this page

I thought I has solved it by hiding the content straight away with changing the container class to hidden (in the header)… but I haven’t, evey now and then i still get a flash of unstyled content.

Does anyone have any ideas of what else I could do to prevent this “FOUC”

The code is simplified as:


<head>
	<link rel="stylesheet" href="mystles.css.php?" />
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script> 
	<script type="text/javascript"> $('.containerClass').css({"visibility":"hidden" });</script>
</head>

<body>

	<div id="container" class = "containerClass">
		// containes a bunch of text and images
	</div>
	
	<script>
		$(document).ready(function()
		{
			doStuff(); // do all the masonary work
			$('.containerClass').css({"visibility":"visible"});
		}
	</script>
</body>

*Note, containerClass in the css is just : .containerClass {visibility:visible;} (so this page looks okay in a non script environment)

It almost works … most of the time, the content is hidden in container before the masonary starts animating and laying out,
but every now and then it looks like you get a flash of cached content of what the page would look like if js was off.

How to avoid, any ideas?

Example page: http://www.surreyforum.co.uk/xz-articles/

JS usually takes a while to load, and in the mean time you see what you’d see with JS off. Because you are hiding the content with JS, that hiding takes a while to happen. A more reliable approach would be to hide the content in the CSS file itself, and then override that with JS.

BUT … that’s not a good way to go in this case, because it means that anyone with JS off will see nothing at all—ever.

So a better approach is to set up the gallery so that it works just fine without JS, and then let the masonry script add that extra bit of spice when it’s ready. This is easy to do with masonry (and it’s what you have anyway … so personally I’d just recommend you lost the visibility: hidden altogether).

Thanks for the !!fast!! response

Yes, I can’t just use the css approach, since it needs to work in a non js environment too

I do actually set this so it looks fine in a non js environment (even works in IE7)… But that’s the issue
When a user has JavaScript enabled, they see this “flicker” of the the non-js environment page (this page looks fine, but it looks strange when flickering from styled to then animating in position)

I’m scratching my head, I’ve spent days looking for ways to make this acceptable … flicker is very annoying

Are you saying it’s not possible to do any better than it currently is (avoiding the flicker is impossible if I want to satisfy both js and non-js yet still animate)

Hm, yeah, I’m not sure, really. You could try a few things, like loading the masonry script before other scripts (apart from the jquery library, of course). You could also try placing the scripts at the bottom of the page. (Yes, that might make it slower, but I prefer to put them theere, and you never know till you try.)

I would definitely remove the hiding JS though, as I don’t think it improves things at all. I used masonry just last week and it looked fine, although the elements it was applying to were all the same height, which helps a lot.

Other things to look at would be to optimize the backend so that things load faster (gzipping, chaining files and all that), as the server seems to be dragging along at the moment.

Hi,

You can try the hybrid trick of adding a class of js to the html tag as soon as the page runs rather than waiting for an element to load and then hiding it (which is what document ready does and is then too late to hide the flash).

Then you use css to hide the element before it can even show.

.js .element{display:none}

Heck, that’s clever. Thanks for the link, Paul. :slight_smile:

That might just work, there is just one small change I would use, and that’s not to use display:none, but to use visibility:hidden (otherwise you’ll get jumps in the container div)

Yes that would be fine :slight_smile: (I would have assumed that you’d held the space open with a fixed height on the container anyway height but visibility:hidden on the elements concerned should do that also).

It’s not a fixed hight

I’m still seeing the FOUC issue, I’m now using this:


<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>	
<style type="text/css">
      .hasJsFouc #container{visiblilty:hidden;}
</style>
<script type="text/javascript">
      $('html').addClass('hasJsFouc');
      $(document).ready(function() {
        $('#imgloading ').show();
      });     
</script>
</head>

and then just un-hide later with :


<script>
$(document).ready(function()
{
	var $container = $('#container').masonry();
	$container.css({"visibility":"hidden"}).imagesLoaded(function(){	
		$('#container').css({"visibility":"visible"});
		$('#container').masonry(// stuff);   
	});
});
</script>

Every now and then, I still see the page as if there was no js

Hm, the only flaw I see to that whole setup is that it still requires the jQuery library to load before the class gets added to the <html> element. Why not make it the very first thing the browser has to do? (I say this without knowing much about what order the browser does things in, but meh … worth a try.)

Here’s a simple demo:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script>
    var html = document.querySelector('html');
    html.className = "js";
</script>
<style>
    .js {color: red;}
</style>

[I]other jQuery and CSS stuff here ...[/I]

</head>
<body>
    <p>some content</p>		
</body>
</html>

If you use document.write it waits until the page is ready. you will still get FOUC sometimes.

Method number 7 is what i use. it ads class js to the html tag before anything else. there is no FOUC ever - never! Additionally its not using jquery so it does not have to download jquery before it can work. and you can place all your js at the bottom. aside from this tiny bit you place in the head. http://www.websitecodetutorials.com/code/javascript/add-css-with-javascript.phpWord.


<script type="text/javascript">
document.documentElement.className = 'js';
</script>
<style type="text/css">
html.js #method7 {color:magenta;}
</style>


I’ll give it a try, it sounds promising… my hair has almost fallen out over this, so lets hope I can hold on to the last few strands :s

You need to have it before the main css file otherwise the css will load before the js can get hold of it.

Ralph’s and Erics version are how to do it without jquery but you would do the same if using jquery but without query would be best (Ralph’s version won’t work in IE7 due to the querySelector rule he was using). The relevant js is first in the html and because you are adding to to the html element that will be rendered straight away so you don’t have to wait for it.

I’ve used the method loads of times without problems and it always cures the problem.

Unless of course there is something else going on in your page that is giving you the flash.