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); // failsafeHook 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
- Add the HTML overlay just inside <body>.
- Add the CSS (or merge into your existing bundle).
- Add the JS helper and ensure it runs on every page.
- (Optional) Wire
showLoader/hideLoaderinto SPA route changes or long-running fetches.
0 comments
Please log in to comment.