0

I am creating a website where I want to create a loader. But I put the link tag inside head, it won't show the loader unless the big stylesheet loads.

If I open up firefox/chrome's developer tools -> responsive view, and enable the network tab -> emulate 2G speed, I can see clearly that the stylesheets are loading, then the loader animation is shown, and then the script loads. But I have big stylesheets and wanted to show the animated logo even before the stylesheets are loaded.

For example: [ The loaders are not prominent here, this works best with html files ]

<head>
    <style>
        html, body { margin: 0 ; padding: 0 }

        #loader-head {
            height: 100vh ;
            width: 100% ;
            display: flex ;
            justify-content: center ;
            align-items: center ;
            flex-direction: column ;
            z-index: 10000 ;
            position: fixed ;
            top: 0 ;
            left: 0 ;
            background-color: #25DD84 ;
        }

        #loader-head > #loader { width: 150px ; height: 150px ; position: relative }

        #loader-head > #loader > .loaders {
            position: absolute ;
            width: 50px ;
            height: 50px ;
            background-color: #fff ;
            border-radius: 4px ;
            box-shadow: 0 0 6px #fff ;
            animation: loaderChase 2s ease infinite ;
        }

        #loader-head p {
            font-size: 48px ;
            position: relative ;
            color: #fff ;
            overflow: hidden ;
            text-shadow: 0 0 6px #fff ;
        }

        #loader-head p::before {
            content: 'Loading...' ;
            position: absolute ;
            top: 0 ;
            left: 0 ;
            width: 100% ;
            background: linear-gradient(45deg, #fff, #fff, #fff, #ff5, #f55, #55f) ;
            background-size: 200% ;
            background-clip: text ;
            -webkit-background-clip: text ;
            color: transparent ;
            animation: loaderTextAnim 1s ease infinite 0.75s ;
        }

        @keyframes loaderChase {
            0% { top: 0 ; left: 0 }
            12.5%, 25% { top: 0 ; left: 50% }
            37.5%, 50% { top: 50% ; left: 50% }
            62.5%, 75% { top: 50% ; left: 0 }
            87.5%, 100% { top: 0 ; left: 0 }
        }

        @keyframes loaderTextAnim {
            0% { background-position: 200% }
            90%, 100% { background-position: 0% }
        }
    </style>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">
</head>

<body>
    <div id="loader-head">
        <div id="loader">
            <div class="loaders" style="animation-delay: 200ms"></div>
            <div class="loaders" style="animation-delay: 900ms"></div>
            <div class="loaders" style="animation-delay: 1600ms"></div>
        </div>
        <p>Loading...</p>
    </div>

    Hello!

    <script>
        window.onload = function() {
            document.getElementById('loader-head').remove()
        }
    </script>
</body>

But if I put the link tag inside the tag the animation is shown:

<head>
    <style>
        html, body { margin: 0 ; padding: 0 }

        #loader-head {
            height: 100vh ;
            width: 100% ;
            display: flex ;
            justify-content: center ;
            align-items: center ;
            flex-direction: column ;
            z-index: 10000 ;
            position: fixed ;
            top: 0 ;
            left: 0 ;
            background-color: #25DD84 ;
        }

        #loader-head > #loader { width: 150px ; height: 150px ; position: relative }

        #loader-head > #loader > .loaders {
            position: absolute ;
            width: 50px ;
            height: 50px ;
            background-color: #fff ;
            border-radius: 4px ;
            box-shadow: 0 0 6px #fff ;
            animation: loaderChase 2s ease infinite ;
        }

        #loader-head p {
            font-size: 48px ;
            position: relative ;
            color: #fff ;
            overflow: hidden ;
            text-shadow: 0 0 6px #fff ;
        }

        #loader-head p::before {
            content: 'Loading...' ;
            position: absolute ;
            top: 0 ;
            left: 0 ;
            width: 100% ;
            background: linear-gradient(45deg, #fff, #fff, #fff, #ff5, #f55, #55f) ;
            background-size: 200% ;
            background-clip: text ;
            -webkit-background-clip: text ;
            color: transparent ;
            animation: loaderTextAnim 1s ease infinite 0.75s ;
        }

        @keyframes loaderChase {
            0% { top: 0 ; left: 0 }
            12.5%, 25% { top: 0 ; left: 50% }
            37.5%, 50% { top: 50% ; left: 50% }
            62.5%, 75% { top: 50% ; left: 0 }
            87.5%, 100% { top: 0 ; left: 0 }
        }

        @keyframes loaderTextAnim {
            0% { background-position: 200% }
            90%, 100% { background-position: 0% }
        }
    </style>
</head>

<body>
    <div id="loader-head">
        <div id="loader">
            <div class="loaders" style="animation-delay: 200ms"></div>
            <div class="loaders" style="animation-delay: 900ms"></div>
            <div class="loaders" style="animation-delay: 1600ms"></div>
        </div>
        <p>Loading...</p>
    </div>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">

    Hello!

    <script>
        window.onload = function() {
            document.getElementById('loader-head').remove()
        }
    </script>
</body>

So if I put the <link> inside <body>, the animation loader is shown when the CSS files are loading. But putting the <link> inside <body> is a terrible idea and a bad practice according to some.

In this test I am loading the files without actually doing anything with them. But in my original code, every CSS files are needed.

How can I load the loader concurrently when the CSS files are loading without moving the <link> tags inside the <body> tag?

15 Volts
  • 1,946
  • 15
  • 37
  • 1
    because it loads later, but both example here works, it is just that content loads too fast to set animation on screen, try both codes with hudge images to make sure it takes a few seconds to laod it all.you can set your link in between

    and

    tag so it is not inside body but loads later;) see about it question : https://stackoverflow.com/questions/3037725/is-it-wrong-to-place-the-script-tag-after-the-body-tag

    – G-Cyrillus Nov 09 '20 at 17:49
  • Yes, the content loads faster, but on a 2G connection, it doesn't. If you just copy the 2 codes above, in two separate files, open them in a browser one at a time, open the developer console, emulate 2G connection, and refresh the page, you will see that the first loader doesn't appear even for a brief amount of time, the link are fetched and then the body loads and puff! The loader in the second example should work because it first shows the loader, and loads the stylesheets in the body. TBH, my stylesheets are gzipped, but still takes 5 - 10 seconds on GPRS connection! – 15 Volts Nov 09 '20 at 18:04
  • How is the idea of adding the css code in preload, something like this and then using JS to create a link element append that to `document.head` as child? It works most of the times with CSS, but fails 50% of the times with JS. In my code window.onload ensures loader is shown until everything is loaded right.. – 15 Volts Nov 09 '20 at 20:14

1 Answers1

0

My simple solution was to append the CSS file URLs to the JS and let it append it to the document.head. It gets a bit lengthy here, but it works flawlessly and most probably doesn't violate any HTML5 standards:


<head>
    <style>
    html, body { margin: 0 ; padding: 0 }

    #loader-head {
        height: 100vh ;
        width: 100% ;
        display: flex ;
        justify-content: center ;
        align-items: center ;
        flex-direction: column ;
        z-index: 10000 ;
        position: fixed ;
        top: 0 ;
        left: 0 ;
        background-color: #25DD84 ;
    }

    #loader-head > #loader { width: 150px ; height: 150px ; position: relative }

    #loader-head > #loader > .loaders {
        position: absolute ;
        width: 50px ;
        height: 50px ;
        background-color: #fff ;
        border-radius: 4px ;
        box-shadow: 0 0 6px #fff ;
        animation: loaderChase 2s ease infinite ;
    }

    #loader-head p {
        font-size: 48px ;
        position: relative ;
        color: #fff ;
        overflow: hidden ;
        text-shadow: 0 0 6px #fff ;
    }

    #loader-head p::before {
        content: 'Loading...' ;
        position: absolute ;
        top: 0 ;
        left: 0 ;
        width: 100% ;
        background: linear-gradient(45deg, #fff, #fff, #fff, #ff5, #f55, #55f) ;
        background-size: 200% ;
        background-clip: text ;
        -webkit-background-clip: text ;
        color: transparent ;
        animation: loaderTextAnim 1s ease infinite 0.75s ;
    }

    @keyframes loaderChase {
        0% { top: 0 ; left: 0 }
        12.5%, 25% { top: 0 ; left: 50% }
        37.5%, 50% { top: 50% ; left: 50% }
        62.5%, 75% { top: 50% ; left: 0 }
        87.5%, 100% { top: 0 ; left: 0 }
    }

    @keyframes loaderTextAnim {
        0% { background-position: 200% }
        90%, 100% { background-position: 0% }
    }
    </style>

    <link rel="preload" as="style" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="preload" as="style" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <link rel="preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
    <link rel="preload" as="style" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">

    <script>
        const cssFiles = `
        stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min
        stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min
        cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min
        cdn.jsdelivr.net/npm/water.css@2/out/water
        `.split("\n")

        for(let cssFile of cssFiles) {
            cssFile = cssFile.trim()

            if(cssFile) {
                let link = document.createElement('link')
                link.rel = 'stylesheet'
                link.type = 'text/css'
                link.href = `https://${cssFile}.css`
                document.head.appendChild(link)
            }
        }

        window.onload = function() {
            document.getElementById('loader-head').remove()
        }
    </script>
</head>

<body>
    <div id="loader-head">
        <div id="loader">
            <div class="loaders" style="animation-delay: 200ms"></div>
            <div class="loaders" style="animation-delay: 900ms"></div>
            <div class="loaders" style="animation-delay: 1600ms"></div>
        </div>
        <p>Loading...</p>
    </div>

    Hello!
</body>

Here's a long animation:

enter image description here

15 Volts
  • 1,946
  • 15
  • 37