0

I'm trying to make a simple page load progress bar with CSS and a bit of JS. I already made a working css, but the problem is the bar shows up after page change, when I would like it to firstly finish the css progress bar animation and then load next page.

HTML animation code:

<div class="progress-css"></div>

CSS animation code:

:root {
  --progress-duration: 0.8s;
  --progress-height: 2.5px;
  --progress-color: rgb(35,163,255);
  --progress-color-ending: rgba(35,163,255,0.2);
  --progress-shadow: 0 0 3px 2px rgba(0,148,255,0.23);
}

.progress-css {
  position: fixed;
  height: var(--progress-height);
  width: 100%;
  background-color: transparent;
  z-index: 99999;
  box-shadow: none;
  transition: 0.8s;
  animation: progress-load var(--progress-duration);
  -webkit-animation: progress-load var(--progress-duration);
  animation-timing-function: ease-in-out;
}

@keyframes progress-load {
  0% {
    background-color: var(--progress-color);
    box-shadow: var(--progress-shadow);
    width: 0%;
  }
  20% {
    background-color: var(--progress-color);
    width: 20%;
  }
  25% {
    background-color: var(--progress-color);
    width: 28%;
  }
  90% {
    background-color: var(--progress-color);
    width: 85%;
  }
  100% {
    width: 100%;
    background-color: var(--progress-color-ending);
    box-shadow: none;
  }
}

Now, when I will click on a <a href="subpage.html">Redirect</a> tag on a website, it will load the specified page, and then it will display progress animation. I would like it to firstly display progress animation, and then load the next page.

I would be grateful for an answer to my question.

3
  • So basically you have a loader? Commented Jan 1, 2021 at 17:05
  • @DumbCoder7 Yes, it's a loader displayed as a progress bar at the top of the page. If you don't know what I mean, go to YouTube and switch between pages, you will see a red loading bar at the top of the page every time you switch the page. Commented Jan 1, 2021 at 17:08
  • If you have the transition duration fixed, why not request the page load after that duration? Commented Jan 1, 2021 at 17:11

1 Answer 1

1

JavaScript has an animationend event that can be used to detect when a keyframe animation is complete. Ideally you would wait to add this listener after any required data (if applicable) is completed loading so it doesn't just arbitrarily advance if loading is still in-progress.

document.querySelector('.progress-css').addEventListener('animationend', e=>{
    //go to next page or similar
    window.location.href = 'subpage.html';
});

Updated example based on more details from the comments:

const progressBar = document.querySelector('.progress-css');

//add a listener to all of the links; modify the query if it should be restricted to specific links
document.querySelectorAll('a').forEach(link => {
  link.addEventListener('click', e => {
    e.preventDefault(); //stop the default behavior of navigating to a link when clicking an <a> tag
    setupLoadingBar( link.href );
  });
});

const setupLoadingBar = url => {
  const cleanupLoadingBarAndNavigate = e => {
    progressBar.removeEventListener('animationend', cleanupLoadingBarAndNavigate); //removing this each time is important to ensure that it doesn't run multiple times if you don't actually navigate away

    progressBar.classList.remove('loading');
   
    alert('Navigate to: '+url);

    //uncomment this to actually navigate to the url
    //window.location.href = url;
  }
  
  progressBar.classList.add('loading');
  progressBar.addEventListener('animationend', cleanupLoadingBarAndNavigate);
}
:root {
  --progress-duration: 4s;
  --progress-height: 2.5px;
  --progress-color: rgb(35,163,255);
  --progress-color-ending: rgba(35,163,255,0.2);
  --progress-shadow: 0 0 3px 2px rgba(0,148,255,0.23);
}

.progress-css {
  position: fixed;
  height: var(--progress-height);
  width: 100%;
  background-color: transparent;
  z-index: 99999;
  box-shadow: none;
  transition: 0.8s;
  display:none;
}

.loading {
  display:block;
  animation: progress-load var(--progress-duration);
  -webkit-animation: progress-load var(--progress-duration);
  animation-timing-function: ease-in-out;
}

@keyframes progress-load {
  0% {
    background-color: var(--progress-color);
    box-shadow: var(--progress-shadow);
    width: 0%;
  }
  20% {
    background-color: var(--progress-color);
    width: 20%;
  }
  25% {
    background-color: var(--progress-color);
    width: 28%;
  }
  90% {
    background-color: var(--progress-color);
    width: 85%;
  }
  100% {
    width: 100%;
    background-color: var(--progress-color-ending);
    box-shadow: none;
  }
}
<a href="about.html">About</a>
<a href="contact.html">Contact</a>

<div class="progress-css"></div>

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer, but what if I have multiple links on my website? Also, when I ran this code, it made an infinite redirect loop to subpage.html alternating with progress bar animation.
@talaing, can you explain more of what you mean by "load" in this case? Are you trying to do some type of preloading where the link is loaded via JavaScript/AJAX in the background, or just wanting to display the animation before changing pages to give the illusion of something loading? (It's a valid UX technique; no shame in faking it.) If it's the former (preloading), that's far beyond the scope of a SO question. I can help more with the latter though.
No need to preload specified page in the background - I just want to make illusion of something loading.
@talaing updated the answer with a new code sample that shows how to do it with multiple links

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.