<div class="loader" id="loader" role="progressbar" aria-label="Page loading" aria-hidden="true"><div class="loader-bar" id="loader-bar"></div></div>
<main class="demo">
<h1>Top loading bar</h1>
<p>Trigger a request and watch the bar creep along the top edge, then complete once the response is in.</p>
<div class="buttons">
<button type="button" id="fast">Fast request</button>
<button type="button" id="slow">Slow request</button>
</div>
<p class="status" id="status" aria-live="polite">Idle</p>
</main>*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
background: #f8fafc;
color: #0f172a;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.loader {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 3px;
z-index: 100;
opacity: 0;
transition: opacity 0.4s ease;
pointer-events: none;
}
.loader.active {
opacity: 1;
}
.loader-bar {
width: 0;
height: 100%;
background: #2563eb;
box-shadow: 0 0 10px #3b82f6, 0 0 4px #3b82f6;
transition: width 0.3s ease;
}
.demo {
max-width: 440px;
text-align: center;
}
.demo h1 {
font-size: 1.5rem;
margin: 0 0 10px;
}
.demo p {
color: #475569;
line-height: 1.6;
margin: 0 0 24px;
}
.buttons {
display: flex;
justify-content: center;
gap: 10px;
}
.buttons button {
font: inherit;
font-weight: 600;
padding: 11px 20px;
border: 0;
border-radius: 10px;
background: #0f172a;
color: #ffffff;
cursor: pointer;
transition: background 0.15s ease;
}
.buttons button:hover {
background: #1e293b;
}
.buttons button:disabled {
opacity: 0.5;
cursor: default;
}
.status {
margin: 20px 0 0 !important;
font-size: 0.875rem;
font-weight: 500;
}const loader = document.getElementById("loader");
const bar = document.getElementById("loader-bar");
const status = document.getElementById("status");
const buttons = document.querySelectorAll(".buttons button");
let progress = 0;
let trickle = null;
let fade = null;
let reset = null;
function set(value) {
progress = Math.min(value, 99.4);
bar.style.width = progress + "%";
}
function start() {
clearInterval(trickle);
clearTimeout(fade);
clearTimeout(reset);
bar.style.transition = "";
loader.classList.add("active");
loader.setAttribute("aria-hidden", "false");
set(8);
trickle = setInterval(function() {
const step = (100 - progress) * 0.08 * Math.random();
set(progress + step);
}, 250);
}
function done() {
clearInterval(trickle);
bar.style.width = "100%";
fade = setTimeout(function() {
loader.classList.remove("active");
loader.setAttribute("aria-hidden", "true");
reset = setTimeout(function() {
bar.style.transition = "none";
bar.style.width = "0";
bar.offsetWidth;
bar.style.transition = "";
progress = 0;
}, 400);
}, 300);
}
function simulate(duration, label) {
buttons.forEach(function(b) { b.disabled = true; });
status.textContent = "Loading " + label;
start();
setTimeout(function() {
done();
status.textContent = "Loaded in " + (duration / 1000).toFixed(1) + " seconds";
buttons.forEach(function(b) { b.disabled = false; });
}, duration);
}
document.getElementById("fast").addEventListener("click", function() {
simulate(1200, "the dashboard");
});
document.getElementById("slow").addEventListener("click", function() {
simulate(4500, "the full report");
});Click any element to find its code Esc
Check this code before you run it
It came from a shared link. It runs with fewer permissions, so it cannot open pop-ups, submit forms or start downloads.
element.animate() call shows up here as it plays.