47

I have a webpage which heavily makes use of jQuery.

My goal is to only show the page when everything is ready.

With that I want to avoid showing the annoying page rendering to the user.

I tried this so far (#body_holder is a wrapper inside body):

$(function(){
    $('#body_holder').hide();
});
$(window).load(function() {
    $("#body_holder").show();
});

This works completely fine, but messes up the layout.

The problem is that hiding the wrapper interferes with the other jQuery functions and plugins used (eg layout-plugin).

So I guess there must be another trick to do this. Maybe lay a picture or div over the body until window.load has occurred?

What approaches do you use?

EDIT:

The solution most likely has to be another way than display:none or hide();

user229044
  • 232,980
  • 40
  • 330
  • 338
Email
  • 2,395
  • 3
  • 35
  • 63
  • 3
    Have you thought about using CSS to apply a display:none to the #body_holder, then using $(document).ready(function(){ $("#body_holder").show(); }); to bring it into vision once the DOM is ready? – Ohgodwhy Mar 03 '12 at 23:26
  • 2
    If you specify image sizes in your HTML, the page won't be so annoyingly 'jumpy' when the page is loaded. If you do this right, the rendering will probably be a lot less annoying than having to wait until everything is loaded before you can see or do anything at all. Please rethink if you really want to do this. – GolezTrol Mar 03 '12 at 23:27
  • @Ohgodwhy yeah. thats actually the first i tried. display:none on the body. but it is the same as my example. problem still the same. it hides but on-show the layout and all other stuff is messed up. – Email Mar 03 '12 at 23:28
  • @ GolezTrol thanks. i don't have any images on the page. it renders content and layout. – Email Mar 03 '12 at 23:29
  • 1
    Instead of using display:none, use opacity:0. and filter:alpha(opacity=0); – Ohgodwhy Mar 03 '12 at 23:30

10 Answers10

52

Anything done with jQuery will normally have to wait for document.ready, which is too late IMHO.

Put a div on top, like so:

<div id="cover"></div>

set some styles:

#cover {position: fixed; height: 100%; width: 100%; top:0; left: 0; background: #000; z-index:9999;}

and hide it with JS when all elements are loaded:

$(window).on('load', function() {
   $("#cover").hide();
});

Or if for some reason your script uses even longer time then the DOM elements to load, set an interval to check the type of some function that loads the slowest, and remove the cover when all functions are defined!

$(window).on('load', function() {
    $("#cover").fadeOut(200);
});

//stackoverflow does not fire the window onload properly, substituted with fake load

function newW()
{
    $(window).load();
}
setTimeout(newW, 1000);
#cover {position: fixed; height: 100%; width: 100%; top:0; left: 0; background: #000; z-index:9999; 
    font-size: 60px; text-align: center; padding-top: 200px; color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<ul>
    <li>This</li>
    <li>is</li>
    <li>a</li>
    <li>simple</li>
    <li>test</li>
    <li>of</li>
    <li>a</li>
    <li>cover</li>
</ul>

<div id="cover">LOADING</div>
Abrar Jahin
  • 13,970
  • 24
  • 112
  • 161
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • This is'nt your wrapper, it's a new element that is positioned fixed and has a high z-index, you can probably place the element anywhere in your code, and it will cover your site until it is removed by JS, that means you keep your other site elements visible, but covered by the "cover" element. – adeneo Mar 03 '12 at 23:50
  • Thx & sorry. i messed up code trying. This actually works :) Do you think i could make it more fancy by showing pink unicorns and stars? ;) – Email Mar 04 '12 at 00:05
  • What's with the downvote, feel free to explain if the answer is in some way wrong ? – adeneo Mar 04 '12 at 00:38
  • Nope, you removed it as the accepted answer, which is ok, someone else downvoted earlier, but who cares, at least you got it working :-) – adeneo Mar 04 '12 at 01:09
  • Setting the timeout in the fiddle is a bit lame. :/ – kaiser Apr 27 '12 at 12:59
  • @kaiser - More lame to comment on a two month old answer ? The timeout is just to show the effect, as window.load does not fire in the JSfiddle frame, so unless you force a window.load, the fiddle does'nt work even though the code would work with a regular website. Anyways the answer above this one seems to be the correct one? – adeneo Apr 27 '12 at 14:36
  • I love it when CSS is the core of a jQuery solution; because prior to learning jQuery I would live by CSS being able to fix mostly any task. – Alexander Dixon Jan 13 '17 at 20:21
  • Won't that be damaging for CEO? I heard that crawlers do inspect the page as it looks with js turned off, and covers may be suspicious for them. Will be happy to be proven wrong. – I Hafid Feb 22 '17 at 23:17
  • 1
    @IHafid - yes, it could potentially be damaging for SEO, but crawlers these days are smart enough to figure out most things, including ajax and frameworks etc, so it's not a given either. – adeneo Feb 23 '17 at 06:24
47

Here is a jQuery solution for those looking:

Hide the body with css then show it after the page is loaded:

CSS:

html { visibility:hidden; }

JavaScript

$(document).ready(function() {
  document.getElementsByTagName("html")[0].style.visibility = "visible";
});

The page will go from blank to showing all content when the page is loaded, no flash of content, no watching images load etc.

9ete
  • 3,692
  • 1
  • 34
  • 32
  • 1
    I think no downsides if you use jquery. – PascalVKooten Jan 10 '16 at 17:33
  • 2
    $ is jQuery not pure JavaScript. – Kyle Pennell Feb 11 '16 at 17:22
  • 3
    Much the neatest solution - using the 'visibility' attribute of the 'html' element itself eliminates the need for wrapper kludges. – Velojet Nov 27 '17 at 02:32
  • Fabulous approach if the web page is opened in an existing browser tab. However, if the page is launched from another browser tab with _blank, there is a brief (but still annoying) 'flash' until the new web page (with the code above embedded) takes control. Any way to hide that 'flash' between browser tabs? Thanks! – ND_Coder Jun 25 '23 at 11:35
31

You should try setting visibility to hidden instead of display:none. Setting visibility to hidden will retain all elements positions and dimensions, thus it shouldn't create layout problems.

Igor Jerosimić
  • 13,621
  • 6
  • 44
  • 53
  • this is slick and works. thanks +1. i hope it is cross-browser valid. – Email Mar 04 '12 at 01:05
  • 2
    When the page is loading, then the document.style.visibility element cannot be set (it is null until later on). However, my boss showed me you can set document.style.opacity = 0. – Colin Dec 12 '17 at 01:03
5

Start your HTML with:

<body style="opacity:0;">

At the end of your script:

document.body.style.opacity = 1;

tecnobillo
  • 161
  • 2
  • 6
4

Stumbled upon this and tried @9ete's solution but it didn't help me. This worked instead:

CSS:

html { visibility:hidden; }

JS:

window.addEventListener('load', function () {
    document.getElementsByTagName("html")[0].style.visibility = "visible";
});

As per documentation for window, the load event is fired after all the content (images included) is loaded while $document says that ready is fired after only the DOM is ready.

Tanay
  • 41
  • 3
2

Your question is valid, but I would not get in a practice of hiding or covering the page while things are spinning up.

It keeps the user from understanding what's happening on the page. While lots of things may need to load, different parts of the page should spring to life as they're loaded. You should get in the practice of locking controls that are not ready, perhaps displaying a spinner or some other progress indicator over them. Or setting the cursor to wait on loading items.

This keeps the user in the loop and allows him to see and interact with parts as they come online instead of obscuring all parts until everything is ready.

You will normally want to load the things the user needs the quickest access to, usually stuff above the fold, first. Loading is a prioritization that can easily be coordinated with Promises.

At the very least seeing the page allows the user to get his bearings and decide what to do. Be transparent.

Mario
  • 6,572
  • 3
  • 42
  • 74
2

I was seeking a non-javascript solution so I found one that is working on most browsers in acceptable manner.

Since the loading order of CSS rules matters;

  • Define the hiding class in the first CSS file or inline in head.
.hidden-onpage-load{ display: none; } 
  • In the body, the class can be used as
<div class="hidden-onpage-load"> ... </div>
  • Redefine it inline or in a CSS file after all other CSS and JS files are loaded
.hidden-onpage-load{ display: block; } 
Sami Altundag
  • 238
  • 2
  • 6
0

The simplest solution I've come up with is to wrap the body in a as suggested previously, but set it as hidden from the get go, then use JQuery (or javascript) to unhide on load after all components are loaded.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="bodyDiv" hidden>

Hello World!

</div>
<script>
$(document).ready(function() {

  // add JQuery widget loads here
  
  $("#bodyDiv").show(); // reveal complete page
})
</script>
will
  • 153
  • 3
  • 6
0

Don't forget, a lot of frameworks use javascript to structure a page. To prevent the page from showing before these modification have been made you'll need to do something like what is described here (e.g. run a script at the end of the page to show the real contents of the page):

Detect if any JavaScript function is running

John
  • 3,458
  • 4
  • 33
  • 54
-1

If you have a div #bodyholder then you can put display:none in your CSS for it and then with jQuery do:

$(document).ready(function() {
     $('#body_holder').show();
});

I don't see why hiding a div should interfere with the loading of anything, because all it means is it is hidden. However, if you have lots of jQuery being used then make sure you wrap it in $(document).ready which will make sure that the DOM is fully loaded before the Javascript is executed

A further point is that HTML/CSS is designed for progressive loading, and if you do it properly then you can get a nice progressive loading of content for your users. I personally wouldn't want my users getting a white screen for a few seconds until everything was loaded. Move your Javascript to the end of the page so that it doesn't block loading and get content onto the screen as quickly as possible.

christophmccann
  • 4,181
  • 7
  • 42
  • 66
  • hi. this is exactly the same as my example. css can only hide the div if dom is ready. it was my first attempt doing the hide with css. problem stays obviously the same. my jquery alters layout and hides div's. i eg use http://layout.jquery-dev.net/. the page at show() is messed up. i really search for an elegant way to overlay the wrapper somehow. – Email Mar 03 '12 at 23:33
  • 1
    layout plugin needs to be able to set dimensions so hiding main content element won't be a good idea – charlietfl Mar 03 '12 at 23:51
  • @ charlietfl THANX you are actually the first here who considers this. i made it now bold in my question. – Email Mar 03 '12 at 23:52