Announcements
Loading page...

↩ Back to discussion list

Build a loading page spinner

3 weeks ago ⏱ 2 min read 👁 5 views 📘 Tutorial

CSS HTML JAVASCRIPT Web Development

Build a Page Loading Spinner (HTML/CSS/JS)

A lightweight, theme-ready spinner you can drop into any page. It shows while the page (or a fetch) is loading and hides automatically when ready.


Markup

Place this near the top of <body> so it overlays everything.

<div class="page-loader" id="pageLoader" aria-hidden="true">
  <div class="page-loader-spinner" role="status" aria-label="Loading"></div>
</div>
:root {
  --spinner-size: 54px;
  --spinner-color: #96f5dd;
  --spinner-backdrop: rgba(0, 20, 34, 0.45);
}

.page-loader {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--spinner-backdrop);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 9999;
  transition: opacity 0.25s ease, visibility 0.25s ease;
}

.page-loader.is-hidden {
  opacity: 0;
  visibility: hidden;
}

.page-loader-spinner {
  width: var(--spinner-size);
  height: var(--spinner-size);
  border-radius: 50%;
  border: 4px solid rgba(150, 245, 221, 0.25);
  border-top-color: var(--spinner-color);
  animation: spinner-rotate 0.9s linear infinite;
}

@keyframes spinner-rotate {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .page-loader-spinner { animation: none; border-top-color: rgba(150,245,221,0.8); }
}
const loader = document.getElementById("pageLoader");
const showLoader = () => loader?.classList.remove("is-hidden");
const hideLoader = () => loader?.classList.add("is-hidden");

document.addEventListener("DOMContentLoaded", hideLoader);
window.addEventListener("load", hideLoader);
setTimeout(hideLoader, 2500); // failsafe
Loading preview...

Hook into fetch/navigation (optional)

async function fetchWithSpinner(url, opts) {
  try {
    showLoader();
    const res = await fetch(url, opts);
    return res;
  } finally {
    hideLoader();
  }
}

Accessibility

  • Keep role="status" and aria-label="Loading" on the spinner.
  • Hide the overlay quickly to avoid trapping focus.
  • Offer reduced-motion support (see media query above).

Theming tips

  • For light themes, set --spinner-backdrop: rgba(255,255,255,0.65); and a darker --spinner-color.
  • You can define the vars per theme class, e.g. html.theme-light { … }.

Drop-in checklist

  1. Add the HTML overlay just inside <body>.
  2. Add the CSS (or merge into your existing bundle).
  3. Add the JS helper and ensure it runs on every page.
  4. (Optional) Wire showLoader/hideLoader into SPA route changes or long-running fetches.

Was this post helpful?

Log in to vote on tutorial helpfulness.

by @codewithstephen
👍 0 ❤️ 0 😊 0 👎 0 ☹️ 0

0 comments

Please log in to comment.