How to Build a JavaScript Page Loading Animation

Previously, we learned how to create a JavaScript page loading animation with GSAP. Today, let’s make another beautiful loading animation—this time without using any external JS libraries!

Final product imageFinal product imageFinal product image
What You’ll Be Creating

To better understand what we’re going to build, check out the demo page. Be sure to click on the menu links to repeat the animation.

As both animations have similarities, I’ll borrow some content sections from the previous tutorial. This will help keep each tutorial detailed and independent. 

Page Animation Demo

For this tutorial our demo won’t live on CodePen. As we need different pages to showcase the animation, I decided that it’s better to host it on GitHub. Here’s the project structure:

1
panels-animation/
2
├── about.html
3
├── contact.html
4
├── index.html
5
├── main.css
6
└── main.js

Before we continue, it’s worth noting that the inspiration for this demo is taken from the rather lovely Nine Orchard’s website.

screenshot of the 9 orchards websitescreenshot of the 9 orchards websitescreenshot of the 9 orchards website

1. Begin With the Page Markup

Let’s describe the markup for the index.html page. This will be similar to the other pages.

Inside it, we’ll place:

  • A typical page header
  • The panels that will be responsible for splitting the screen into seven equal parts.
  • The main element where the page’s main content will live.

Additionally, we’ll import:

With all the above in mind, here’s the associated markup:

1
<!doctype html>
2
<html lang="en">
3
  <head>
4
    <meta charset="utf-8">
5
    <meta name="viewport" content="width=device-width, initial-scale=1">
6
    <link rel="preconnect" href="https://fonts.gstatic.com">
7
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap">
8
    <link rel="stylesheet" href="main.css">
9
    <title>Simple JavaScript Page Loading Animation</title>
10
  </head>
11
  
12
  <body>
13
    <header class="page-header">
14
      <nav>
15
        <ul>
16
          <li>
17
            <a href="index.html">Home</a>
18
          </li>
19
          <!-- more list items -->
20
        </ul>
21
      </nav>
22
    </header>
23
    
24
    <ul class="panels">
25
      <li class="panel" style="--index: 3"></li>
26
      <li class="panel" style="--index: 2"></li>
27
      <li class="panel" style="--index: 1"></li>
28
      <li class="panel" style="--index: 0"></li>
29
      <li class="panel" style="--index: 1"></li>
30
      <li class="panel" style="--index: 2"></li>
31
      <li class="panel" style="--index: 3"></li>
32
    </ul>
33
    
34
    <main class="page-main">
35
      <div>
36
        <h1>Home Page</h1>
37
        <!-- put more content here -->
38
      </div>
39
    </main>
40
    
41
    <script src="main.js"></script>   
42
  </body>
43
</html>

Consider the inline styles that we add to the panels. As we’ll see later, we’ll use the index CSS variable to animate them. The bigger the value, the more time it’ll take for the associated element to animate.

2. Define Some Basic Styles

Next, we’ll continue with some CSS variables and reset styles:

1
:root {
2
  --panel-width: calc(100% / 7);
3
  --darkblue: #02020c;
4
  --white: #fff;
5
  --lightgray: #fafafb;
6
}
7

8
* {
9
  padding: 0;
10
  margin: 0;
11
  box-sizing: border-box;
12
}
13

14
ul {
15
  list-style: none;
16
}
17

18
a {
19
  color: inherit;
20
  text-decoration: none;
21
}
22

23
h1 {
24
  font-size: 3rem;
25
}
26

27
body {
28
  height: 100vh;
29
  font-family: "Montserrat", sans-serif;
30
  color: var(--white);
31
  background: var(--darkblue);
32
  overflow: hidden;
33
}

Three things to note:

  • The panel-width variable will determine the panel width.
  • The page height will be equal to the viewport height.
  • We’ll hide any potential scrollbars that might appear depending on the amount of page content.

3. Specify the Main Styles

Let’s now concentrate on the main styles. We’ll leave out the header styles as they haven’t any importance.

The Panels

The panels will be fixed-positioned elements, and their width and left property values will depend on the panel-width variable. That said, the left value for the first panel will be 0, for the second one around 14.28%, for the third one around 28.5%, and so on. Their height will be equal to the viewport height and invisible by default. We’ll use the clip-path property to squeeze and move them to the bottom part of the page.

Main Element

The main element will be fullscreen with horizontally and vertically centered content. For simplicity, we’ll only put a heading and a link, but you can put anything you like. Again, by default, all this content will be invisible and sit 100px away from its original position. 

Here are the relevant styles:

1
/*CUSTOM VARIABLES HERE*/
2

3
.panels .panel {
4
  position: fixed;
5
  top: 0;
6
  left: 0;
7
  bottom: 0;
8
  width: calc(var(--panel-width) + 1px);
9
  clip-path: inset(100% 0 0 0);
10
  background: var(--lightgray);
11
  transition: all 1s cubic-bezier(0.25, 1, 0.25, 1);
12
}
13

14
.panels .panel:nth-child(2) {
15
  left: var(--panel-width);
16
}
17

18
.panels .panel:nth-child(3) {
19
  left: calc(var(--panel-width) * 2);
20
}
21

22
.panels .panel:nth-child(4) {
23
  left: calc(var(--panel-width) * 3);
24
}
25

26
.panels .panel:nth-child(5) {
27
  left: calc(var(--panel-width) * 4);
28
}
29

30
.panels .panel:nth-child(6) {
31
  left: calc(var(--panel-width) * 5);
32
}
33

34
.panels .panel:nth-child(7) {
35
  left: calc(var(--panel-width) * 6);
36
}
37

38
.page-main {
39
  display: flex;
40
  height: 100%;
41
  padding: 100px 15px;
42
  overflow-y: auto;
43
}
44

45
.page-main > div {
46
  text-align: center;
47
  margin: auto;
48
}
49

50
.page-main > div > * {
51
  opacity: 0;
52
  transition: all 0.5s ease-out;
53
}
54

55
.page-main h1 {
56
  transform: translateY(-100px);
57
}
58

59
.page-main p {
60
  font-size: 20px;
61
  margin-top: 20px;
62
  transform: translateY(100px);
63
}

info
if you check the width value of the panels, you’ll notice there’s an extra pixel. Its job is to make the panels overlap a little bit, and thus prevent the blue borders (their color will depend on the page color) between the adjacent panels.  
The blue lines that appear between the panelsThe blue lines that appear between the panelsThe blue lines that appear between the panels

4. Fire the Animations

When the page loads, the following animations have to play in this order:

  1. First, the panels should appear from bottom to top.
  2. Then, the panels should disappear and move to the top.
  3. Finally, all page contents should become visible.

During the first two steps, the panels will be transitioned with some delay. As we’ve discussed before, this will depend on the value of their index variable.

Mimic a Timeline

To create a sequence of tweens as we did the last time with GSAP’s Timeline, we’ll take advantage of a lesser-known event called transitionend. This event fires each time a CSS transition finishes and gives us the ability to synchronize animations.

Of course, we aren’t interested in all transitions, instead, we only care about the panels’ transitions and specifically the transitions of the last animated panel. In our case, the last animated panels will be the first and seventh (last) ones as both have index: 3

The transition delay of the last panelThe transition delay of the last panelThe transition delay of the last panel

As you’ll see in the code, we’ll work with the last one, but we could equally have used the first one. To better understand it, try to give the selected panel a large delay of around 1s and see how the animations get out of sync.

In terms of the code logic, we’ll do the following things in this order:

  1. First, when the page loads, we’ll add the loaded class to the body.
  2. Then, we’ll wait till the transition of the last panel finishes—this will fire twice in total. At that point, we’ll add another class to the body. The first time we’ll add the second-round class, while the second time, we’ll add the third-round.

After the completion of our transitions, the body will have these classes:

The classes attached to the bodyThe classes attached to the bodyThe classes attached to the body

Here’s the JavaScript code:

1
const body = document.body;
2
const lastPanel = document.querySelector(".panels .panel:last-child");
3

4
window.addEventListener("load", () => {
5
  body.classList.add("loaded");
6
  
7
  lastPanel.addEventListener("transitionend", () => {
8
    if (body.classList.contains("second-round")) {
9
      body.classList.add("third-round");
10
    } else {
11
      body.classList.add("second-round");
12
    }
13
  });
14
});

Instead of the load event, we could have used the DOMContentLoaded event.

And the corresponding styles:

1
.loaded .panels .panel {
2
  clip-path: inset(0);
3
  transition-delay: calc(var(--index) * 0.06s);
4
}
5

6
.loaded.second-round .panels .panel {
7
  clip-path: inset(0 0 100% 0);
8
}
9

10
.loaded.third-round {
11
  overflow: auto;
12
}
13

14
.loaded.third-round .page-main > div > * {
15
  opacity: 1;
16
  transform: none;
17
}

Conclusion

Congrats, folks! We managed to build an attractive JavaScript page loading animation by staggering animations thanks to the transitionend event. Obviously, for more heavy use of animations, a library like GSAP is a more robust approach to follow. Feel free to extend the demo as you wish and share it with me!

As always, thanks a lot for reading!

More Projects to Practice

Take a look at these projects on Tuts+ that use the clip-path property to apply different kinds of animations.


This content originally appeared on Envato Tuts+ Tutorials and was authored by George Martsoukos

Previously, we learned how to create a JavaScript page loading animation with GSAP. Today, let’s make another beautiful loading animation—this time without using any external JS libraries!

Final product imageFinal product imageFinal product image
What You'll Be Creating

To better understand what we’re going to build, check out the demo page. Be sure to click on the menu links to repeat the animation.

As both animations have similarities, I’ll borrow some content sections from the previous tutorial. This will help keep each tutorial detailed and independent. 

Page Animation Demo

For this tutorial our demo won’t live on CodePen. As we need different pages to showcase the animation, I decided that it’s better to host it on GitHub. Here's the project structure:

1
panels-animation/
2
├── about.html
3
├── contact.html
4
├── index.html
5
├── main.css
6
└── main.js

Before we continue, it’s worth noting that the inspiration for this demo is taken from the rather lovely Nine Orchard’s website.

screenshot of the 9 orchards websitescreenshot of the 9 orchards websitescreenshot of the 9 orchards website

1. Begin With the Page Markup

Let’s describe the markup for the index.html page. This will be similar to the other pages.

Inside it, we’ll place:

  • A typical page header
  • The panels that will be responsible for splitting the screen into seven equal parts.
  • The main element where the page’s main content will live.

Additionally, we’ll import:

With all the above in mind, here’s the associated markup:

1
<!doctype html>
2
<html lang="en">
3
  <head>
4
    <meta charset="utf-8">
5
    <meta name="viewport" content="width=device-width, initial-scale=1">
6
    <link rel="preconnect" href="https://fonts.gstatic.com">
7
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap">
8
    <link rel="stylesheet" href="main.css">
9
    <title>Simple JavaScript Page Loading Animation</title>
10
  </head>
11
  
12
  <body>
13
    <header class="page-header">
14
      <nav>
15
        <ul>
16
          <li>
17
            <a href="index.html">Home</a>
18
          </li>
19
          <!-- more list items -->
20
        </ul>
21
      </nav>
22
    </header>
23
    
24
    <ul class="panels">
25
      <li class="panel" style="--index: 3"></li>
26
      <li class="panel" style="--index: 2"></li>
27
      <li class="panel" style="--index: 1"></li>
28
      <li class="panel" style="--index: 0"></li>
29
      <li class="panel" style="--index: 1"></li>
30
      <li class="panel" style="--index: 2"></li>
31
      <li class="panel" style="--index: 3"></li>
32
    </ul>
33
    
34
    <main class="page-main">
35
      <div>
36
        <h1>Home Page</h1>
37
        <!-- put more content here -->
38
      </div>
39
    </main>
40
    
41
    <script src="main.js"></script>   
42
  </body>
43
</html>

Consider the inline styles that we add to the panels. As we'll see later, we'll use the index CSS variable to animate them. The bigger the value, the more time it'll take for the associated element to animate.

2. Define Some Basic Styles

Next, we’ll continue with some CSS variables and reset styles:

1
:root {
2
  --panel-width: calc(100% / 7);
3
  --darkblue: #02020c;
4
  --white: #fff;
5
  --lightgray: #fafafb;
6
}
7
8
* {
9
  padding: 0;
10
  margin: 0;
11
  box-sizing: border-box;
12
}
13
14
ul {
15
  list-style: none;
16
}
17
18
a {
19
  color: inherit;
20
  text-decoration: none;
21
}
22
23
h1 {
24
  font-size: 3rem;
25
}
26
27
body {
28
  height: 100vh;
29
  font-family: "Montserrat", sans-serif;
30
  color: var(--white);
31
  background: var(--darkblue);
32
  overflow: hidden;
33
}

Three things to note:

  • The panel-width variable will determine the panel width.
  • The page height will be equal to the viewport height.
  • We’ll hide any potential scrollbars that might appear depending on the amount of page content.

3. Specify the Main Styles

Let’s now concentrate on the main styles. We’ll leave out the header styles as they haven’t any importance.

The Panels

The panels will be fixed-positioned elements, and their width and left property values will depend on the panel-width variable. That said, the left value for the first panel will be 0, for the second one around 14.28%, for the third one around 28.5%, and so on. Their height will be equal to the viewport height and invisible by default. We’ll use the clip-path property to squeeze and move them to the bottom part of the page.

Main Element

The main element will be fullscreen with horizontally and vertically centered content. For simplicity, we’ll only put a heading and a link, but you can put anything you like. Again, by default, all this content will be invisible and sit 100px away from its original position. 

Here are the relevant styles:

1
/*CUSTOM VARIABLES HERE*/
2
3
.panels .panel {
4
  position: fixed;
5
  top: 0;
6
  left: 0;
7
  bottom: 0;
8
  width: calc(var(--panel-width) + 1px);
9
  clip-path: inset(100% 0 0 0);
10
  background: var(--lightgray);
11
  transition: all 1s cubic-bezier(0.25, 1, 0.25, 1);
12
}
13
14
.panels .panel:nth-child(2) {
15
  left: var(--panel-width);
16
}
17
18
.panels .panel:nth-child(3) {
19
  left: calc(var(--panel-width) * 2);
20
}
21
22
.panels .panel:nth-child(4) {
23
  left: calc(var(--panel-width) * 3);
24
}
25
26
.panels .panel:nth-child(5) {
27
  left: calc(var(--panel-width) * 4);
28
}
29
30
.panels .panel:nth-child(6) {
31
  left: calc(var(--panel-width) * 5);
32
}
33
34
.panels .panel:nth-child(7) {
35
  left: calc(var(--panel-width) * 6);
36
}
37
38
.page-main {
39
  display: flex;
40
  height: 100%;
41
  padding: 100px 15px;
42
  overflow-y: auto;
43
}
44
45
.page-main > div {
46
  text-align: center;
47
  margin: auto;
48
}
49
50
.page-main > div > * {
51
  opacity: 0;
52
  transition: all 0.5s ease-out;
53
}
54
55
.page-main h1 {
56
  transform: translateY(-100px);
57
}
58
59
.page-main p {
60
  font-size: 20px;
61
  margin-top: 20px;
62
  transform: translateY(100px);
63
}
info
if you check the width value of the panels, you’ll notice there’s an extra pixel. Its job is to make the panels overlap a little bit, and thus prevent the blue borders (their color will depend on the page color) between the adjacent panels.  
The blue lines that appear between the panelsThe blue lines that appear between the panelsThe blue lines that appear between the panels

4. Fire the Animations

When the page loads, the following animations have to play in this order:

  1. First, the panels should appear from bottom to top.
  2. Then, the panels should disappear and move to the top.
  3. Finally, all page contents should become visible.

During the first two steps, the panels will be transitioned with some delay. As we’ve discussed before, this will depend on the value of their index variable.

Mimic a Timeline

To create a sequence of tweens as we did the last time with GSAP’s Timeline, we’ll take advantage of a lesser-known event called transitionend. This event fires each time a CSS transition finishes and gives us the ability to synchronize animations.

Of course, we aren’t interested in all transitions, instead, we only care about the panels’ transitions and specifically the transitions of the last animated panel. In our case, the last animated panels will be the first and seventh (last) ones as both have index: 3

The transition delay of the last panelThe transition delay of the last panelThe transition delay of the last panel

As you’ll see in the code, we’ll work with the last one, but we could equally have used the first one. To better understand it, try to give the selected panel a large delay of around 1s and see how the animations get out of sync.

In terms of the code logic, we’ll do the following things in this order:

  1. First, when the page loads, we’ll add the loaded class to the body.
  2. Then, we’ll wait till the transition of the last panel finishes—this will fire twice in total. At that point, we’ll add another class to the body. The first time we’ll add the second-round class, while the second time, we’ll add the third-round.

After the completion of our transitions, the body will have these classes:

The classes attached to the bodyThe classes attached to the bodyThe classes attached to the body

Here’s the JavaScript code:

1
const body = document.body;
2
const lastPanel = document.querySelector(".panels .panel:last-child");
3
4
window.addEventListener("load", () => {
5
  body.classList.add("loaded");
6
  
7
  lastPanel.addEventListener("transitionend", () => {
8
    if (body.classList.contains("second-round")) {
9
      body.classList.add("third-round");
10
    } else {
11
      body.classList.add("second-round");
12
    }
13
  });
14
});
Instead of the load event, we could have used the DOMContentLoaded event.

And the corresponding styles:

1
.loaded .panels .panel {
2
  clip-path: inset(0);
3
  transition-delay: calc(var(--index) * 0.06s);
4
}
5
6
.loaded.second-round .panels .panel {
7
  clip-path: inset(0 0 100% 0);
8
}
9
10
.loaded.third-round {
11
  overflow: auto;
12
}
13
14
.loaded.third-round .page-main > div > * {
15
  opacity: 1;
16
  transform: none;
17
}

Conclusion

Congrats, folks! We managed to build an attractive JavaScript page loading animation by staggering animations thanks to the transitionend event. Obviously, for more heavy use of animations, a library like GSAP is a more robust approach to follow. Feel free to extend the demo as you wish and share it with me!

As always, thanks a lot for reading!

More Projects to Practice

Take a look at these projects on Tuts+ that use the clip-path property to apply different kinds of animations.


This content originally appeared on Envato Tuts+ Tutorials and was authored by George Martsoukos


Print Share Comment Cite Upload Translate Updates
APA

George Martsoukos | Sciencx (2023-02-24T07:38:11+00:00) How to Build a JavaScript Page Loading Animation. Retrieved from https://www.scien.cx/2023/02/24/how-to-build-a-javascript-page-loading-animation/

MLA
" » How to Build a JavaScript Page Loading Animation." George Martsoukos | Sciencx - Friday February 24, 2023, https://www.scien.cx/2023/02/24/how-to-build-a-javascript-page-loading-animation/
HARVARD
George Martsoukos | Sciencx Friday February 24, 2023 » How to Build a JavaScript Page Loading Animation., viewed ,<https://www.scien.cx/2023/02/24/how-to-build-a-javascript-page-loading-animation/>
VANCOUVER
George Martsoukos | Sciencx - » How to Build a JavaScript Page Loading Animation. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/02/24/how-to-build-a-javascript-page-loading-animation/
CHICAGO
" » How to Build a JavaScript Page Loading Animation." George Martsoukos | Sciencx - Accessed . https://www.scien.cx/2023/02/24/how-to-build-a-javascript-page-loading-animation/
IEEE
" » How to Build a JavaScript Page Loading Animation." George Martsoukos | Sciencx [Online]. Available: https://www.scien.cx/2023/02/24/how-to-build-a-javascript-page-loading-animation/. [Accessed: ]
rf:citation
» How to Build a JavaScript Page Loading Animation | George Martsoukos | Sciencx | https://www.scien.cx/2023/02/24/how-to-build-a-javascript-page-loading-animation/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.