Loaders
Stairs Bounce Loader
A single-div CSS loading spinner: a bouncing ball climbs a set of steps drawn with layered box-shadows, no dependency needed.
Loading preview
Advertisement
Ad space reserved for a future placement
Source code
"use client";
interface StairsBounceLoaderProps {
accentColor?: string;
stepColor?: string;
label?: string;
className?: string;
}
export function StairsBounceLoader({
accentColor = "#3f3cf2",
stepColor = "#4b5563",
label = "Loading",
className,
}: StairsBounceLoaderProps) {
return (
<div
role="status"
aria-label={label}
className={["stairs-bounce-loader-wrapper", className].filter(Boolean).join(" ")}
style={{ ["--bounce-ball" as string]: accentColor, ["--bounce-step" as string]: stepColor }}
>
<div className="loader" />
<style jsx>{`
.loader {
position: relative;
width: 120px;
height: 90px;
margin: 0 auto;
}
.loader:before {
content: "";
position: absolute;
bottom: 30px;
left: 32px;
height: 30px;
width: 30px;
border-radius: 50%;
background: var(--bounce-ball);
animation: loading-bounce 0.5s ease-in-out infinite alternate;
}
.loader:after {
content: "";
position: absolute;
right: 0;
top: 0;
height: 7px;
width: 45px;
border-radius: 4px;
box-shadow:
0 5px 0 var(--bounce-step),
-35px 50px 0 var(--bounce-step),
-70px 95px 0 var(--bounce-step);
animation: loading-step 1s ease-in-out infinite;
}
@keyframes loading-bounce {
0% {
transform: scale(1, 0.7);
}
40% {
transform: scale(0.8, 1.2);
}
60% {
transform: scale(1, 1);
}
100% {
bottom: 140px;
}
}
@keyframes loading-step {
0% {
box-shadow:
0 10px 0 rgba(0, 0, 0, 0),
0 10px 0 var(--bounce-step),
-35px 50px 0 var(--bounce-step),
-70px 90px 0 var(--bounce-step);
}
100% {
box-shadow:
0 10px 0 var(--bounce-step),
-35px 50px 0 var(--bounce-step),
-70px 90px 0 var(--bounce-step),
-70px 90px 0 rgba(0, 0, 0, 0);
}
}
@media (prefers-reduced-motion: reduce) {
.loader:before,
.loader:after {
animation-duration: 2.5s;
}
}
`}</style>
</div>
);
}
Usage
Import the component and use it like this.
import { StairsBounceLoader } from "./StairsBounceLoader";
export default function Example() {
return <StairsBounceLoader accentColor="#3f3cf2" stepColor="#4b5563" label="Loading" />;
}
Dependencies
No external dependencies.
Usage notes
Pass accentColor (ball) and stepColor (steps) hex values, and an optional label for the accessible status announcement.