208

I have a section on our website that loads quite slowly as it's doing some intensive calls.

Any idea how I can get a div to say something similar to "loading" to show while the page prepares itself and then vanish when everything is ready?

simhumileco
  • 31,877
  • 16
  • 137
  • 115
Shadi Almosri
  • 11,678
  • 16
  • 58
  • 80

13 Answers13

291

Original Answer

I've needed this and after some research I came up with this (jQuery needed):

First, right after the <body> tag add this:

<div id="loading">
  <img id="loading-image" src="path/to/ajax-loader.gif" alt="Loading..." />
</div>

Then add the style class for the div and image to your CSS:

#loading {
  position: fixed;
  display: block;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  text-align: center;
  opacity: 0.7;
  background-color: #fff;
  z-index: 99;
}

#loading-image {
  position: absolute;
  top: 100px;
  left: 240px;
  z-index: 100;
}

Then, add this javascript to your page (preferably at the end of your page, before your closing </body> tag, of course):

<script>
  $(window).load(function() {
    $('#loading').hide();
  });
</script>

Finally, adjust the position of the loading image and the background-color of the loading div with the style class.

This is it, should work just fine. But of course you should have an ajax-loader.gif somewhere or use base64 url for image's src value. Freebies here. (Right-click > Save Image As...)

Update

For jQuery 3.0 and above you can use:

<script>
  $(window).on('load', function () {
    $('#loading').hide();
  }) 
</script>

Update

The original answer is from jQuery and before flexbox era. You can use many view management libraries / frameworks now like Angular, React and Vue.js. And for CSS you have flexbox option. Below is CSS alternative:

#loading {
  position: fixed;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  opacity: 0.7;
  background-color: #fff;
  z-index: 99;
}

#loading-image {
  z-index: 100;
}
mehyaa
  • 3,302
  • 1
  • 17
  • 18
51

This script will add a div that covers the entire window as the page loads. It will show a CSS-only loading spinner automatically. It will wait until the window (not the document) finishes loading, then it will wait an optional extra few seconds.

  • Works with jQuery 3 (it has a new window load event)
  • No image needed but it's easy to add one
  • Change the delay for more branding or instructions
  • Only dependency is jQuery.

CSS loader code from https://projects.lukehaas.me/css-loaders

    
$('body').append('<div style="" id="loadingDiv"><div class="loader">Loading...</div></div>');
$(window).on('load', function(){
  setTimeout(removeLoader, 2000); //wait for page load PLUS two seconds.
});
function removeLoader(){
    $( "#loadingDiv" ).fadeOut(500, function() {
      // fadeOut complete. Remove the loading div
      $( "#loadingDiv" ).remove(); //makes page more lightweight 
  });  
}
        .loader,
        .loader:after {
            border-radius: 50%;
            width: 10em;
            height: 10em;
        }
        .loader {            
            margin: 60px auto;
            font-size: 10px;
            position: relative;
            text-indent: -9999em;
            border-top: 1.1em solid rgba(255, 255, 255, 0.2);
            border-right: 1.1em solid rgba(255, 255, 255, 0.2);
            border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
            border-left: 1.1em solid #ffffff;
            -webkit-transform: translateZ(0);
            -ms-transform: translateZ(0);
            transform: translateZ(0);
            -webkit-animation: load8 1.1s infinite linear;
            animation: load8 1.1s infinite linear;
        }
        @-webkit-keyframes load8 {
            0% {
                -webkit-transform: rotate(0deg);
                transform: rotate(0deg);
            }
            100% {
                -webkit-transform: rotate(360deg);
                transform: rotate(360deg);
            }
        }
        @keyframes load8 {
            0% {
                -webkit-transform: rotate(0deg);
                transform: rotate(0deg);
            }
            100% {
                -webkit-transform: rotate(360deg);
                transform: rotate(360deg);
            }
        }
        #loadingDiv {
            position:absolute;;
            top:0;
            left:0;
            width:100%;
            height:100%;
            background-color:#000;
        }
This script will add a div that covers the entire window as the page loads. It will show a CSS-only loading spinner automatically. It will wait until the window (not the document) finishes loading.

  <ul>
    <li>Works with jQuery 3, which has a new window load event</li>
    <li>No image needed but it's easy to add one</li>
    <li>Change the delay for branding or instructions</li>
    <li>Only dependency is jQuery.</li>
  </ul>

Place the script below at the bottom of the body.

CSS loader code from https://projects.lukehaas.me/css-loaders

<!-- Place the script below at the bottom of the body -->

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Victor Stoddard
  • 3,582
  • 2
  • 27
  • 27
  • How to add this for imag tags? – Mano M Feb 21 '19 at 08:03
  • 1
    @ManoM `$(window).on("load", handler)` fires when all DOM objects finished loading, including images, scripts, even iframes. If you want to wait for a specific image to load, use `$('#imageId').on("load", handler)` – Victor Stoddard Feb 22 '19 at 00:59
  • This for me is only working when the page first loads, i.e. when the browser/tab is opened or refreshed. However, it does not show up when the page is loading after it has been opened. I have a page with toggles showing different contents and when toggling between contents it takes a while to load. Is there a way in which I could adapt this same code to load not only the first time the page is opened but every time it is taking a while to load? – Joehat Dec 06 '19 at 18:08
  • 1
    @Joehat replace `$( "#loadingDiv" ).remove();` with `$( "#loadingDiv" ).hide();` and add `$( "#loadingDiv" ).show();` before `setTimeout(removeLoader, 2000);`. I had the div removed to make the page more lightweight, but this fix makes it reusable. – Victor Stoddard Dec 07 '19 at 17:12
  • I tried your code.. It's strange. When I call my page it shows a blank page (it's loading content). After few seconds (I think contents are loaded) it shows the loader for 2 seconds, than it shows the full page. You can take a look: https://www.criferrara.it/crigest/toshiba/ – sunlight76 Jan 17 '20 at 18:55
  • @sunlight76 You added the – Victor Stoddard Jan 22 '20 at 00:03
37

window.onload = function(){ document.getElementById("loading").style.display = "none" }
#loading {width: 100%;height: 100%;top: 0px;left: 0px;position: fixed;display: block; z-index: 99}

#loading-image {position: absolute;top: 40%;left: 45%;z-index: 100} 
<div id="loading">
<img id="loading-image" src="img/loading.gif" alt="Loading..." />
</div>  

Page loading image with simplest fadeout effect created in JS:

Ced
  • 1,293
  • 5
  • 23
  • 34
Dariusz J
  • 558
  • 6
  • 11
10

I have another below simple solution for this which perfectly worked for me.

First of all, create a CSS with name Lockon class which is transparent overlay along with loading GIF as shown below

.LockOn {
    display: block;
    visibility: visible;
    position: absolute;
    z-index: 999;
    top: 0px;
    left: 0px;
    width: 105%;
    height: 105%;
    background-color:white;
    vertical-align:bottom;
    padding-top: 20%; 
    filter: alpha(opacity=75); 
    opacity: 0.75; 
    font-size:large;
    color:blue;
    font-style:italic;
    font-weight:400;
    background-image: url("../Common/loadingGIF.gif");
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-position: center;
}

Now we need to create our div with this class which cover entire page as an overlay whenever the page is getting loaded

<div id="coverScreen"  class="LockOn">
</div>

Now we need to hide this cover screen whenever the page is ready and so that we can restrict the user from clicking/firing any event until the page is ready

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

Above solution will be fine whenever the page is loading.

Now the question is after the page is loaded, whenever we click a button or an event which will take a long time, we need to show this in the client click event as shown below

$("#ucNoteGrid_grdViewNotes_ctl01_btnPrint").click(function () {
$("#coverScreen").show();
});

That means when we click this print button (which will take a long time to give the report) it will show our cover screen with GIF which gives this result and once the page is ready above windows on load function will fire and which hide the cover screen once the screen is fully loaded.

Roshana Pitigala
  • 8,437
  • 8
  • 49
  • 80
Rinoy Ashokan
  • 1,501
  • 17
  • 14
6

Default the contents to display:none and then have an event handler that sets it to display:block or similar after it's fully loaded. Then have a div that's set to display:block with "Loading" in it, and set it to display:none in the same event handler as before.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • 2
    what event would you use to do this? Javascript page load? or is there a better place? – Miles Dec 05 '09 at 22:29
  • Depends on if you have other JS doing setup stuff for the page - if so, call it after those are done, if not, then document onload works fine. – Amber Dec 05 '09 at 22:30
3

Here's the jQuery I ended up using, which monitors all ajax start/stop, so you don't need to add it to each ajax call:

$(document).ajaxStart(function(){
    $("#loading").removeClass('hide');
}).ajaxStop(function(){
    $("#loading").addClass('hide');
});

CSS for the loading container & content (mostly from mehyaa's answer), as well as a hide class:

#loading {
   width: 100%;
   height: 100%;
   top: 0px;
   left: 0px;
   position: fixed;
   display: block;
   opacity: 0.7;
   background-color: #fff;
   z-index: 99;
   text-align: center;
}

#loading-content {
  position: absolute;
  top: 50%;
  left: 50%;
  text-align: center;
  z-index: 100;
}

.hide{
  display: none;
}

HTML:

<div id="loading" class="hide">
  <div id="loading-content">
    Loading...
  </div>
</div>
rybo111
  • 12,240
  • 4
  • 61
  • 70
  • The problem is, if i have a ajax loaded autocomplete in a input, the loader will appear. – Lucas Jun 09 '17 at 14:08
2

Well, this largely depends on how you're loading the elements needed in the 'intensive call', my initial thought is that you're doing those loads via ajax. If that's the case, then you could use the 'beforeSend' option and make an ajax call like this:

$.ajax({
  type: 'GET',
  url: "some.php",
  data: "name=John&location=Boston",

  beforeSend: function(xhr){           <---- use this option here
     $('.select_element_you_want_to_load_into').html('Loading...');
  },

  success: function(msg){
     $('.select_element_you_want_to_load_into').html(msg);
  }
});

EDIT I see, in that case, using one of the 'display:block'/'display:none' options above in conjunction with $(document).ready(...) from jQuery is probably the way to go. The $(document).ready() function waits for the entire document structure to be loaded before executing (but it doesn't wait for all media to load). You'd do something like this:

$(document).ready( function() {
  $('table#with_slow_data').show();
  $('div#loading image or text').hide();
});
ann
  • 576
  • 1
  • 10
  • 19
btelles
  • 5,390
  • 7
  • 46
  • 78
  • unfortunatly it's not through ajax, it's waiting for the php script to prepare the data from the database, so some of the html elements are loaded then the browser waits for the table of data before loading the rest. Which could look as if the page has stalled, so need something displayed there to show that "something is happening" and not cause the user to move away... – Shadi Almosri Dec 07 '09 at 00:22
  • FYI: The principle of the web (without ajax) is that a server renders an entire page serverside and on completion it sends this result (html) to the browser. If the rendering of the page is halted somewhere in the middle (while you can see the page appearing in the browser), it can't be a php script, because php only runs serverside. – Peter Sep 01 '10 at 12:00
  • See my answer to avoid adding `beforeSend` and `success` to each ajax call. – rybo111 Mar 04 '16 at 17:12
2

My blog will work 100 percent.

function showLoader()
{
    $(".loader").fadeIn("slow");
}
function hideLoader()
{
    $(".loader").fadeOut("slow");
}
.loader {
    position: fixed;
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100%;
    z-index: 9999;
    background: url('pageLoader2.gif') 50% 50% no-repeat rgb(249,249,249);
    opacity: .8;
}
<div class="loader"></div>
developer033
  • 24,267
  • 8
  • 82
  • 108
1

Create a <div> element that contains your loading message, give the <div> an ID, and then when your content has finished loading, hide the <div>:

$("#myElement").css("display", "none");

...or in plain JavaScript:

document.getElementById("myElement").style.display = "none";
Steve Harrison
  • 121,227
  • 16
  • 87
  • 72
  • Simple and gets the job done. From a readability perspective isn't `$("#myElement").hide()` easier on the eyes? – user3613932 May 16 '19 at 01:25
1

This will be in synchronisation with an api call, When the api call is triggered, the loader is shown. When the api call is succesful, the loader is removed. This can be used for either page load or during an api call.

  $.ajax({
    type: 'GET',
    url: url,
    async: true,
    dataType: 'json',
    beforeSend: function (xhr) {
      $( "<div class='loader' id='searching-loader'></div>").appendTo("#table-playlist-section");
      $("html, body").animate( { scrollTop: $(document).height() }, 100);
    },
    success: function (jsonOptions) {
      $('#searching-loader').remove();
      .
      .
    }
  });

CSS

.loader {
  border: 2px solid #f3f3f3;
  border-radius: 50%;
  border-top: 2px solid #3498db;
  width: 30px;
  height: 30px;
  margin: auto;
  -webkit-animation: spin 2s linear infinite; /* Safari */
  animation: spin 2s linear infinite;
  margin-top: 35px;
  margin-bottom: -35px;
}

/* Safari */
@-webkit-keyframes spin {
  0% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
london_utku
  • 1,070
  • 2
  • 16
  • 36
1

for drupal in your theme custom_theme.theme file

function custom_theme_preprocess_html(&$variables) {
$variables['preloader'] = 1;
}

In html.html.twig file after skip main content link in body

{% if preloader %} 
  <div id="test-preloader" >
    <div id="preloader-inner" class="cssload-container">
      <div class="wait-text">{{ 'Please wait...'|t }} </div> 
      <div class="cssload-item cssload-moon"></div>
    </div>
  </div>
{% endif %}  

in css file

#test-preloader {
position: fixed;
background: white;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 9999;
}
.cssload-container .wait-text {
text-align: center;
padding-bottom: 15px;
color: #000;
}

.cssload-container .cssload-item {
 margin: auto;
 position: absolute;
 top: 0;
 right: 0;
 bottom: 0;
 left: 0;
 width: 131px;
 height: 131px;
 background-color: #fff;
 box-sizing: border-box;
 -o-box-sizing: border-box;
 -ms-box-sizing: border-box;
 -webkit-box-sizing: border-box;
 -moz-box-sizing: border-box;
 box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
 -o-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
 -ms-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
 -webkit-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
 -moz-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
 }

.cssload-container .cssload-moon {
border-bottom: 26px solid #008AFA;
border-radius: 50%;
-o-border-radius: 50%;
-ms-border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
animation: spin 1.45s ease infinite;
-o-animation: spin 1.45s ease infinite;
-ms-animation: spin 1.45s ease infinite;
-webkit-animation: spin 1.45s ease infinite;
-moz-animation: spin 1.45s ease infinite;
 }
Pradeep
  • 317
  • 4
  • 9
1

I needed a splash screen, which I implemented by reusing parts of the solutions listed here. It uses Vanilla JS for full backwards-compatibility.

Step 1: Add a background with a spinner gif on top of the page, then remove them when everything is loaded.

body.has-js::before {
  content: '';
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 10;
  height: 100vh;
  width: 100vw;
  pointer-events: none;
  transition: all .2s;
  background: white url('/img/spinner.gif') no-repeat center center / 50px;
}
body.loaded::before {
  opacity: 0;
  width: 0;
  height: 0;
}

Step 2: Add a little script right after the opening body tag to start displaying the load/splash screen.

<body>
  <script>
    // Only show loader if JS is available
    document.body.className += ' has-js';
    // Option 1: Hide loader when 'load' event fires
    window.onload = function() { document.body.className += ' loaded'; }
    // Option 2: Hide loader after 2 seconds, in case the 'load' event never fires
    setTimeout(function(){ document.body.className += ' loaded'; }, 1000 * 2);
  </script>
  <!-- Page content goes after this -->
</body>
Goulven
  • 777
  • 9
  • 20
0

Based on @mehyaa answer, but much shorter:

HTML (right after <body>):

<img id = "loading" src = "loading.gif" alt = "Loading indicator">

CSS:

#loading {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 32px;
  height: 32px;
  /* 1/2 of the height and width of the actual gif */
  margin: -16px 0 0 -16px;
  z-index: 100;
  }

Javascript (jQuery, since I'm already using it):

$(window).load(function() {
  $('#loading').remove();
  });
Francisco Presencia
  • 8,732
  • 6
  • 46
  • 90