SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Enthusiast
    Join Date
    Jan 2008
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    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:

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

  2. #2
    It's all Geek to me silver trophybronze trophy
    ralph.m's Avatar
    Join Date
    Mar 2009
    Location
    Melbourne, AU
    Posts
    24,117
    Mentioned
    448 Post(s)
    Tagged
    8 Thread(s)
    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).
    Facebook | Google+ | Twitter | Web Design Tips | Free Contact Form

    Forum Usage: Tips on posting code samples, images and more

    Forrest Gump: "IE is like a box of chocolates: you never know what you're gonna get."

  3. #3
    SitePoint Enthusiast
    Join Date
    Jan 2008
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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)

  4. #4
    It's all Geek to me silver trophybronze trophy
    ralph.m's Avatar
    Join Date
    Mar 2009
    Location
    Melbourne, AU
    Posts
    24,117
    Mentioned
    448 Post(s)
    Tagged
    8 Thread(s)
    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.
    Facebook | Google+ | Twitter | Web Design Tips | Free Contact Form

    Forum Usage: Tips on posting code samples, images and more

    Forrest Gump: "IE is like a box of chocolates: you never know what you're gonna get."

  5. #5
    The CSS Clinic is open silver trophybronze trophy
    Paul O'B's Avatar
    Join Date
    Jan 2003
    Location
    Hampshire UK
    Posts
    40,295
    Mentioned
    179 Post(s)
    Tagged
    6 Thread(s)
    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}

  6. #6
    It's all Geek to me silver trophybronze trophy
    ralph.m's Avatar
    Join Date
    Mar 2009
    Location
    Melbourne, AU
    Posts
    24,117
    Mentioned
    448 Post(s)
    Tagged
    8 Thread(s)
    Quote Originally Posted by Paul O'B View Post
    You can try the hybrid trick ...
    Heck, that's clever. Thanks for the link, Paul.
    Facebook | Google+ | Twitter | Web Design Tips | Free Contact Form

    Forum Usage: Tips on posting code samples, images and more

    Forrest Gump: "IE is like a box of chocolates: you never know what you're gonna get."

  7. #7
    SitePoint Enthusiast
    Join Date
    Jan 2008
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Paul O'B View Post
    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}
    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)

  8. #8
    The CSS Clinic is open silver trophybronze trophy
    Paul O'B's Avatar
    Join Date
    Jan 2003
    Location
    Hampshire UK
    Posts
    40,295
    Mentioned
    179 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by Mr Tuition View Post
    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 (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).

  9. #9
    SitePoint Enthusiast
    Join Date
    Jan 2008
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's not a fixed hight

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

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

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

  10. #10
    It's all Geek to me silver trophybronze trophy
    ralph.m's Avatar
    Join Date
    Mar 2009
    Location
    Melbourne, AU
    Posts
    24,117
    Mentioned
    448 Post(s)
    Tagged
    8 Thread(s)
    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:

    Code:
    <!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>
    
    other jQuery and CSS stuff here ...
    
    </head>
    <body>
        <p>some content</p>		
    </body>
    </html>
    Facebook | Google+ | Twitter | Web Design Tips | Free Contact Form

    Forum Usage: Tips on posting code samples, images and more

    Forrest Gump: "IE is like a box of chocolates: you never know what you're gonna get."

  11. #11
    SitePoint Wizard bronze trophy PicnicTutorials's Avatar
    Join Date
    Dec 2007
    Location
    Carlsbad, California, United States
    Posts
    3,656
    Mentioned
    15 Post(s)
    Tagged
    0 Thread(s)
    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/...javascript.phpWord.

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

  12. #12
    SitePoint Enthusiast
    Join Date
    Jan 2008
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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

  13. #13
    The CSS Clinic is open silver trophybronze trophy
    Paul O'B's Avatar
    Join Date
    Jan 2003
    Location
    Hampshire UK
    Posts
    40,295
    Mentioned
    179 Post(s)
    Tagged
    6 Thread(s)
    Quote Originally Posted by Mr Tuition View Post
    It's not a fixed hight

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

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

    Code:
    <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
    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.


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •