67

This is a little hard to explain, So I'll try my best

So while a HTML page loads, I'd like there to be a cool loading screen going on. When it finishes loading, I want the loading screen to clear and the HTML document to be shown.

Basically, I want This:

CSS:

/* Absolute Center CSS Spinner */
.loading {
  position: fixed;
  z-index: 999;
  height: 2em;
  width: 2em;
  overflow: show;
  margin: auto;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

/* Transparent Overlay */
.loading:before {
  content: '';
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0,0,0,0.3);
}

/* :not(:required) hides these rules from IE9 and below */
.loading:not(:required) {
  /* hide "loading..." text */
  font: 0/0 a;
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}

.loading:not(:required):after {
  content: '';
  display: block;
  font-size: 10px;
  width: 1em;
  height: 1em;
  margin-top: -0.5em;
  -webkit-animation: spinner 1500ms infinite linear;
  -moz-animation: spinner 1500ms infinite linear;
  -ms-animation: spinner 1500ms infinite linear;
  -o-animation: spinner 1500ms infinite linear;
  animation: spinner 1500ms infinite linear;
  border-radius: 0.5em;
  -webkit-box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
  box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) -1.5em 0 0 0, rgba(0, 0, 0, 0.75) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
}

/* Animation */

@-webkit-keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@-moz-keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@-o-keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes spinner {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

HTML:

<div class="loading">Loading&#8230;</div>

to be happening while the page loads. when the page loads, That is cleared, and the rest of the HTML document is displayed. (I'm making a credits system and while the credits load i just really need it to say it's loading, people complain they can't click anything and i have to tell them all it's just loading)

I'd like to stay away from Ajax as much as possible since I'd like to learn Javascript.

Govind Samrow
  • 9,981
  • 13
  • 53
  • 90
  • How about loading the 'loading' screen first? it may slow down the actual loading process a bit but it would help significantly from a psychological viewpoint – Rebirth Aug 11 '14 at 22:28
  • @Rebirth I could, But do you mean like having a page with the loading screen on it and then redirecting to the real page after like 3 seconds? I could do that, But the thing is, It isn't really loading it, So it just looks a little bit.. childish. Even with that, I'm running this on Jsfiddle, and i don't think it lets you make multiple pages in one project. I'll try it by copying the sites code to my computer though, and see how that works. –  Aug 11 '14 at 22:31
  • I'd say showing the loading screen and requesting the actual page with ajax (sorry I know you wanted to stay away from ajax). and displaying it when it has been loaded with the `success:` option. Also even if it's not really loading, end users will never be the wiser since technology has taught a lot of users that there will be a loading or initiation process. – Rebirth Aug 11 '14 at 22:37
  • @Rebirth I guess I'll have to work out Ajax or do the fake redirect thing until something new comes up here. Thanks for at least trying to help though! –  Aug 11 '14 at 22:40

7 Answers7

90

You can wait until the body is ready:

function onReady(callback) {
  var intervalId = window.setInterval(function() {
    if (document.getElementsByTagName('body')[0] !== undefined) {
      window.clearInterval(intervalId);
      callback.call(this);
    }
  }, 1000);
}

function setVisible(selector, visible) {
  document.querySelector(selector).style.display = visible ? 'block' : 'none';
}

onReady(function() {
  setVisible('.page', true);
  setVisible('#loading', false);
});
body {
  background: #FFF url("https://i.imgur.com/KheAuef.png") top left repeat-x;
  font-family: 'Alex Brush', cursive !important;
}

.page    { display: none; padding: 0 0.5em; }
.page h1 { font-size: 2em; line-height: 1em; margin-top: 1.1em; font-weight: bold; }
.page p  { font-size: 1.5em; line-height: 1.275em; margin-top: 0.15em; }

#loading {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100vw;
  height: 100vh;
  background-color: rgba(192, 192, 192, 0.5);
  background-image: url("https://i.stack.imgur.com/MnyxU.gif");
  background-repeat: no-repeat;
  background-position: center;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css?family=Alex+Brush" rel="stylesheet">
<div class="page">
  <h1>The standard Lorem Ipsum passage</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
    dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div id="loading"></div>

Here is a JSFiddle that demonstrates this technique.


Update

Here is a modern version using promises. The promise is completely optional now, as it is only used for a delay. The DOMContentLoaded event will fire once the page is loaded.

const wait = (delay = 0) =>
  new Promise(resolve => setTimeout(resolve, delay));

const setVisible = (elementOrSelector, visible) => 
  (typeof elementOrSelector === 'string'
    ? document.querySelector(elementOrSelector)
    : elementOrSelector
  ).style.display = visible ? 'block' : 'none';

setVisible('.page', false);
setVisible('#loading', true);

document.addEventListener('DOMContentLoaded', () =>
  wait(1000).then(() => {
    setVisible('.page', true);
    setVisible('#loading', false);
  }));
body {
  background: #FFF url("https://i.imgur.com/KheAuef.png") top left repeat-x;
  font-family: 'Alex Brush', cursive !important;
}

.page    { display: none; padding: 0 0.5em; }
.page h1 { font-size: 2em; line-height: 1em; margin-top: 1.1em; font-weight: bold; }
.page p  { font-size: 1.5em; line-height: 1.275em; margin-top: 0.15em; }

#loading {
  display: flex;
  position: fixed;
  z-index: 100;
  width: 100%;
  height: 100%;
  background-color: rgba(192, 192, 192, 0.5);
  background-image: url("https://i.stack.imgur.com/MnyxU.gif");
  background-repeat: no-repeat;
  background-position: center;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css?family=Alex+Brush" rel="stylesheet">
<div class="page">
  <h1>The standard Lorem Ipsum passage</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
    dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div id="loading"></div>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • You can adjust the timeout for the interval to make it faster or slower to load. – Mr. Polywhirl Aug 11 '14 at 23:28
  • Thanks. Although it may be a tiny bit fake, It does seem cool and it will stick to one page. Thanks a lot. I'll try it and see if it works. –  Aug 11 '14 at 23:42
  • 1
    Checked it out. Looks pretty cool! Again, Thank you for all the help you've done. –  Aug 11 '14 at 23:53
  • @MarkieJonesWTF If you want to learn more about sizing units like `rem`, `vh`, and `vw` then you should check out [A List Apart: Learning to Love the Boring Bits of CSS](http://alistapart.com/article/love-the-boring-bits-of-css). – Mr. Polywhirl Aug 12 '14 at 10:51
  • In your fiddle - how does the loading screen rotate? Didn't find any keyframes, additional resources or code, that would make this happen. Magic? :) – Toastgeraet May 20 '16 at 07:31
  • @Toastgeraet Can't tell if your comment is tongue-in-cheek, but FYI, the picture is GIF – Honinbo Shusaku Jul 20 '16 at 12:10
  • @Abdul Oh - how did I miss that :D - Thanks for the info. Really. Was getting into so much of the new css stuff with animations and so on and thought it had to be something like that. Shame on me. – Toastgeraet Jul 23 '16 at 21:32
  • how to recall it ? sorry for asking in comment section got banned for useless questions guess – Munkhdelger Tumenbayar Dec 13 '17 at 03:56
  • @Mr.Polywhirl, it will load based on the internet speed also? – jvk Mar 23 '19 at 18:43
  • Even if the content is loaded in nano seconds, this function will still take 1 second separately. – Harsh Gaur Oct 16 '22 at 12:32
10

At the beginning of your loading script, just make your

visible through css [display:block;] and make the rest of the page invisible through css[display:none;].

Once the loading is done, just make the loading invisible and the page visible again with the same technique. You can use the document.getElementById() to select the divs you want to change the display.

Edit: Here's what it would sort of look like. When the body finishes loading, it will call the javascript function that will change the display values of the different elements. By default, your style would be to have the page not visible the loading visible.

<head>
    <style>
        #page{
            display: none;
        }
        #loading{
            display: block;
        }
    </style>
    <script>
        function myFunction()
        {
            document.getElementById("page").style.display = "block";
            document.getElementById("loading").style.display = "none";
        }
    </script>
</head>

<body onload="myFunction()">
    <div id="page">

    </div>
    <div id="loading">

    </div>
</body>
Community
  • 1
  • 1
IronWilliamCash
  • 539
  • 5
  • 19
  • 1
    This seems a little bit confusing as I'm new to Javascript. (And I have never used Ajax before, So don't tell me to use it) Could you explain a bit more about document.getElementById() and give me an example please? –  Aug 11 '14 at 22:35
  • Hm. Whenever i load up my page, It comes up completely blank, Like it hasn't loaded, Yet firefox says it has. –  Aug 11 '14 at 22:52
3

To build further upon the ajax part which you may or may not use (from the comments)

a simple way to load another page and replace it with your current one is:

<script>
    $(document).ready( function() {
        $.ajax({
            type: 'get',
            url: 'http://pageToLoad.from',
            success: function(response) {
                // response = data which has been received and passed on to the 'success' function.
                $('body').html(response);
            }
        });
    });
<script>
Rebirth
  • 1,011
  • 8
  • 14
1

If in your site you have ajax calls loading some data, and this is the reason the page is loading slow, the best solution I found is with

$(document).ajaxStop(function(){
    alert("All AJAX requests completed");
});

https://jsfiddle.net/44t5a8zm/ - here you can add some ajax calls and test it.

Vladimir Vladimirov
  • 269
  • 1
  • 2
  • 14
0

I would suggest adding class no-js to your html to nest your CSS selectors under it like:

.loading {
    display: none;
 }

.no-js .loading {
 display: block;
 //....
}

and when you finish loading your credit code remove it:

$('html').removeClass('no-js');

This will hide your loading spinner as there's no no-js class in html it means you already loaded your credit code

Ihab Khattab
  • 351
  • 2
  • 6
  • It's removing the style but it isn't removing the acctual
    for the spinner.
    –  Aug 11 '14 at 23:14
  • Why you need to remove the
    ? you may need to show it again when loading another credit code. in this case you will just add `no-js` class to html `$('html').addClass('no-js');` without the need to re-create spinner
    again
    – Ihab Khattab Aug 11 '14 at 23:18
  • If the div isn't removed, It will just show "Loading...." at the bottom of the credits, And i don't want it to spazz out like that. –  Aug 11 '14 at 23:20
  • are you sure you are removing `no-js` class from html and adding `.loading { display: none; }` to your CSS? – Ihab Khattab Aug 11 '14 at 23:26
0

This method uses the WindowOrWorkerGlobalScope.setInterval(https://developer.mozilla.org/en-US/doc) method to track the ready states of the document & see if the <body> element exists.

// Function > Loader Screen Script
(function LoaderScreenScript(window = window, document = window.document, undefined = window.undefined || void 0) {
    // Initialization > (Processing Time, Condition, Timeout, Loader (...))
    let processingTime = 0,
        condition = function() {
            // Return
            return document.body
        },
        timeout = function() {
            // Return
            return (processingTime * 1e3) / 2
        },
        loaderScreenFontSize = typeof window.loaderScreenFontSize != 'undefined' ? window.loaderScreenFontSize : 14,
        loaderScreenMargin = typeof window.loaderScreenMargin != 'undefined' ? window.loaderScreenMargin : 10,
        loaderScreenMessage = typeof window.loaderScreenMessage != 'undefined' ? window.loaderScreenMessage : 'Loading, please wait&hellip;',
        loaderScreenOpacity = typeof window.loaderScreenOpacity != 'undefined' ? window.loaderScreenOpacity : .75,
        loaderScreenTransition = typeof window.loaderScreenTransition != 'undefined' ? window.loaderScreenTransition : .675,
        loaderScreenWidth = typeof window.loaderScreenWidth != 'undefined' ? window.loaderScreenWidth : 7.5;

    // Function > Update
    function update() {
        // Set Timeout
        setTimeout(function() {
            // Initialization > (Data, Metadata)
            var data = document.createElement('loader-screen-element'),
                metadata = setInterval(function() {
                    /* Logic
                            [if:else if:else statement]
                    */
                    if (document.readyState == 'complete') {
                        // Alpha
                        alpha();

                        // Test
                        test()
                    }
                });

            // Insertion
            document.body.appendChild(data);

            // Style > <body> > Overflow
            document.body.style = ('overflow: hidden !important; pointer-events: none !important; user-drag: none !important; user-select: none !important;' + (document.body.getAttribute('style') || ' ')).trim();

            // Modification > Data
                // Inner HTML
                data.innerHTML =
                    '<style media=all type=text/css>' +
                        'body::selection {' +
                            'background-color: transparent !important;' +
                            'text-shadow: none !important' +
                        '} ' +
                        '@keyframes rotate {' +
                            '0% { transform: rotate(0) }' +
                            'to { transform: rotate(360deg) }' +
                        '}' +
                    '</style>' +
                    "<div style='animation: rotate 1s ease-in-out 0s infinite backwards; border: " + loaderScreenWidth + "px solid rgba(0, 0, 0, " + loaderScreenOpacity + "); border-top-color: rgba(0, 51, 255, " + loaderScreenOpacity + "); border-radius: 50%; height: 75px; margin: 0 auto; margin-bottom: " + loaderScreenMargin + "px; width: 75px'> </div>" +
                    "<small style='color: rgba(127, 127, 127, .675); font-family: \"Open Sans\", \"Calibri Light\", Calibri, sans-serif; font-size: " + loaderScreenFontSize + "px !important; margin: 0 auto; margin-top: " + loaderScreenMargin + "px; text-align: center'> " + loaderScreenMessage + " </small>";

                // Style
                data.style = 'align-items: center; background-color: rgba(255, 255, 255, .98); display: flex; flex-direction: column; height: ' + innerHeight + 'px; justify-content: center; left: 0; margin: auto; max-height: 100% !important; max-width: 100% !important; min-height: 100vh; min-width: 100vh; position: fixed; top: 0; transition: ' + loaderScreenTransition + 's ease-in-out; width: ' + innerWidth + 'px; z-index: 2147483647';

            // Function
                // Alpha
                function alpha() {
                    // Clear Interval
                    clearInterval(metadata)
                };

                // Test
                function test() {
                    // Style > Data
                        // Background Color
                        data.style.backgroundColor = 'transparent';

                        // Opacity
                        data.style.opacity = 0;

                    // Set Timeout
                    setTimeout(function() {
                        // Deletion
                        data.remove();

                        // Modification > <body> > Style
                        document.body.style = document.body.getAttribute('style').replace('overflow: hidden !important;', '').replace('pointer-events: none !important;', '').replace('user-drag: none !important;', '').replace('user-select: none !important;', '');
                        (document.body.getAttribute('style') || '').trim() || document.body.removeAttribute('style')
                    }, ((+getComputedStyle(data).getPropertyValue('animation-delay').replace(/[a-zA-Z]/g, '').trim() + +getComputedStyle(data).getPropertyValue('animation-duration').replace(/[a-zA-Z]/g, '').trim() + +getComputedStyle(data).getPropertyValue('transition-delay').replace(/[a-zA-Z]/g, '').trim() + +getComputedStyle(data).getPropertyValue('transition-duration').replace(/[a-zA-Z]/g, '').trim()) * 1e3) + 100);
                }
        }, timeout())
    };

    /* Logic
            [if:else if:else statement]
    */
    if (condition())
        // Update
        update();

    else {
        // Initialization > Data
        var data = setInterval(function() {
            /* Logic
                    [if:else if:else statement]
            */
            if (condition()) {
                // Update > Processing Time
                processingTime += 1;

                // Update
                update();

                // Metadata
                metadata()
            }
        });

        // Function > Metadata
        function metadata() {
            // Clear Interval
            clearInterval(data);

            /* Logic
                    [if:else if:else statement]

                > Deletion
            */
            if ('data' in window && typeof data == 'undefined')
                delete window.data
        }
    }
})(window, window.document, window.undefined || void 0)

This pre-loading screen was made by Lapys @ https://github.com/LapysDev

Lapys
  • 936
  • 2
  • 11
  • 27
-2
<html>
<div id="filter"></div>
<div id="load"></div>
<input type="button" value="Submit" onclick="myFunction()">
</html>
<style type="text/css">
*{
margin:0;
}
#load{
width:35px;
height:35px;
border-radius:50%;
border:2px solid #f3f3f3;
border-top:2px solid blue;
margin:auto;
right:0;
left:0;
top:40%;
position:fixed;
animation:load 1s linear infinite;
display:none;
}
@keyframes load{
0%{transform:rotate(0deg)}
100%{transform:rotate(360deg)}
}
#filter{
width:100%;
height:100%;
background:rgba(0, 0, 0, 0.5);
position:fixed;
display:none;
}
</style>
<script>
function myFunction(){
document.getElementById('filter').style.display="block";
document.getElementById('load').style.display="block";
window.location="location...";
}
</script>
Tamim
  • 11
  • 2