UI Components Easy
Shimmer Button
A button with a shimmering light sweep effect that glides across periodically, creating an elegant loading or attention animation.
Open in Lab
MCP
css javascript vue svelte
Targets: TS JS HTML React Vue Svelte
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background: #0a0a0a;
color: #f1f5f9;
min-height: 100vh;
}
.demo {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2rem;
padding: 2rem;
}
.demo-title {
font-size: 1.5rem;
font-weight: 700;
color: #e2e8f0;
}
.hint {
color: #525252;
font-size: 0.875rem;
margin-bottom: 1rem;
}
.button-row {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 2rem;
}
/* --- Shimmer button base --- */
.shimmer-btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.875rem 2rem;
border-radius: 10px;
font-size: 0.9375rem;
font-weight: 600;
letter-spacing: 0.01em;
cursor: pointer;
border: none;
outline: none;
color: #fff;
overflow: hidden;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.shimmer-btn:hover {
transform: translateY(-1px);
filter: brightness(1.1);
}
.shimmer-btn:active {
transform: translateY(0);
}
/* Shimmer pseudo-element */
.shimmer-btn::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
120deg,
transparent 0%,
transparent 30%,
rgba(255, 255, 255, 0.25) 45%,
rgba(255, 255, 255, 0.4) 50%,
rgba(255, 255, 255, 0.25) 55%,
transparent 70%,
transparent 100%
);
animation: shimmer-sweep 3s ease-in-out infinite;
pointer-events: none;
}
/* Sizes */
.shimmer-btn--sm {
padding: 0.625rem 1.5rem;
font-size: 0.8125rem;
}
.shimmer-btn--lg {
padding: 1.125rem 2.75rem;
font-size: 1.0625rem;
}
/* Color variants */
.shimmer-btn--blue {
background: #3b82f6;
box-shadow: 0 4px 14px rgba(59, 130, 246, 0.3);
}
.shimmer-btn--purple {
background: #8b5cf6;
box-shadow: 0 4px 14px rgba(139, 92, 246, 0.3);
}
.shimmer-btn--emerald {
background: #10b981;
box-shadow: 0 4px 14px rgba(16, 185, 129, 0.3);
}
.shimmer-btn--rose {
background: #f43f5e;
box-shadow: 0 4px 14px rgba(244, 63, 94, 0.3);
}
.shimmer-btn--dark {
background: #1e293b;
border: 1px solid #334155;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
}
.shimmer-btn--outline {
background: transparent;
color: #94a3b8;
border: 1.5px solid #334155;
transition: transform 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.shimmer-btn--outline:hover {
border-color: #64748b;
color: #f1f5f9;
}
.shimmer-btn--outline::before {
background: linear-gradient(
120deg,
transparent 0%,
transparent 30%,
rgba(148, 163, 184, 0.15) 45%,
rgba(148, 163, 184, 0.25) 50%,
rgba(148, 163, 184, 0.15) 55%,
transparent 70%,
transparent 100%
);
}
/* Shimmer keyframes */
@keyframes shimmer-sweep {
0% {
left: -100%;
}
50%,
100% {
left: 100%;
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.shimmer-btn::before {
animation: none;
display: none;
}
}// Shimmer Button — minimal JS (CSS handles the animation)
(function () {
"use strict";
const buttons = document.querySelectorAll(".shimmer-btn");
buttons.forEach((btn) => {
btn.addEventListener("click", () => {
// Restart shimmer on click for immediate feedback
btn.style.animation = "none";
const before = window.getComputedStyle(btn, "::before");
btn.offsetHeight; // trigger reflow
btn.style.animation = "";
});
});
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Shimmer Button</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="demo">
<h2 class="demo-title">Shimmer Buttons</h2>
<p class="hint">Watch the light sweep across each button</p>
<div class="button-row">
<button class="shimmer-btn shimmer-btn--blue">
Discover More
</button>
<button class="shimmer-btn shimmer-btn--purple">
Upgrade Plan
</button>
<button class="shimmer-btn shimmer-btn--dark">
Learn More
</button>
</div>
<div class="button-row">
<button class="shimmer-btn shimmer-btn--emerald shimmer-btn--lg">
Get Started Free
</button>
<button class="shimmer-btn shimmer-btn--rose shimmer-btn--sm">
Buy Now
</button>
</div>
<div class="button-row">
<button class="shimmer-btn shimmer-btn--outline">
View Details
</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>import { type CSSProperties, type ReactNode, type MouseEvent } from "react";
interface ShimmerButtonProps {
children: ReactNode;
onClick?: (e: MouseEvent<HTMLButtonElement>) => void;
variant?: "blue" | "purple" | "emerald" | "rose" | "dark" | "outline";
size?: "sm" | "md" | "lg";
className?: string;
}
const variantStyles: Record<string, CSSProperties> = {
blue: { background: "#3b82f6", color: "#fff", boxShadow: "0 4px 14px rgba(59,130,246,0.3)" },
purple: { background: "#8b5cf6", color: "#fff", boxShadow: "0 4px 14px rgba(139,92,246,0.3)" },
emerald: { background: "#10b981", color: "#fff", boxShadow: "0 4px 14px rgba(16,185,129,0.3)" },
rose: { background: "#f43f5e", color: "#fff", boxShadow: "0 4px 14px rgba(244,63,94,0.3)" },
dark: {
background: "#1e293b",
color: "#fff",
border: "1px solid #334155",
boxShadow: "0 4px 14px rgba(0,0,0,0.3)",
},
outline: { background: "transparent", color: "#94a3b8", border: "1.5px solid #334155" },
};
const sizeStyles: Record<string, CSSProperties> = {
sm: { padding: "0.625rem 1.5rem", fontSize: "0.8125rem" },
md: { padding: "0.875rem 2rem", fontSize: "0.9375rem" },
lg: { padding: "1.125rem 2.75rem", fontSize: "1.0625rem" },
};
export function ShimmerButton({
children,
onClick,
variant = "blue",
size = "md",
className = "",
}: ShimmerButtonProps) {
const isOutline = variant === "outline";
const shimmerGradient = isOutline
? "linear-gradient(120deg, transparent 0%, transparent 30%, rgba(148,163,184,0.15) 45%, rgba(148,163,184,0.25) 50%, rgba(148,163,184,0.15) 55%, transparent 70%, transparent 100%)"
: "linear-gradient(120deg, transparent 0%, transparent 30%, rgba(255,255,255,0.25) 45%, rgba(255,255,255,0.4) 50%, rgba(255,255,255,0.25) 55%, transparent 70%, transparent 100%)";
const btnStyle: CSSProperties = {
position: "relative",
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
borderRadius: "10px",
fontWeight: 600,
letterSpacing: "0.01em",
cursor: "pointer",
border: "none",
outline: "none",
overflow: "hidden",
transition: "transform 0.2s ease, box-shadow 0.2s ease, filter 0.2s ease",
...sizeStyles[size],
...variantStyles[variant],
};
const shimmerStyle: CSSProperties = {
position: "absolute",
top: 0,
left: "-100%",
width: "100%",
height: "100%",
background: shimmerGradient,
animation: "shimmer-sweep 3s ease-in-out infinite",
pointerEvents: "none",
};
return (
<>
<style>{`
@keyframes shimmer-sweep {
0% { left: -100%; }
50%, 100% { left: 100%; }
}
@media (prefers-reduced-motion: reduce) {
.shimmer-pseudo { display: none !important; }
}
`}</style>
<button
onClick={onClick}
className={className}
style={btnStyle}
onMouseEnter={(e) => {
e.currentTarget.style.transform = "translateY(-1px)";
e.currentTarget.style.filter = "brightness(1.1)";
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = "translateY(0)";
e.currentTarget.style.filter = "brightness(1)";
}}
>
<span className="shimmer-pseudo" style={shimmerStyle} />
<span style={{ position: "relative", zIndex: 1 }}>{children}</span>
</button>
</>
);
}
export default function ShimmerButtonDemo() {
return (
<div
style={{
minHeight: "100vh",
background: "#0a0a0a",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: "2rem",
padding: "2rem",
fontFamily: "system-ui, -apple-system, sans-serif",
}}
>
<h2 style={{ fontSize: "1.5rem", fontWeight: 700, color: "#e2e8f0" }}>Shimmer Buttons</h2>
<p style={{ color: "#525252", fontSize: "0.875rem" }}>
Watch the light sweep across each button
</p>
<div style={{ display: "flex", flexWrap: "wrap", gap: "2rem", justifyContent: "center" }}>
<ShimmerButton variant="blue">Discover More</ShimmerButton>
<ShimmerButton variant="purple">Upgrade Plan</ShimmerButton>
<ShimmerButton variant="dark">Learn More</ShimmerButton>
</div>
<div style={{ display: "flex", flexWrap: "wrap", gap: "2rem", justifyContent: "center" }}>
<ShimmerButton variant="emerald" size="lg">
Get Started Free
</ShimmerButton>
<ShimmerButton variant="rose" size="sm">
Buy Now
</ShimmerButton>
</div>
<div style={{ display: "flex", flexWrap: "wrap", gap: "2rem", justifyContent: "center" }}>
<ShimmerButton variant="outline">View Details</ShimmerButton>
</div>
</div>
);
}<script setup>
const variants = {
blue: { background: "#3b82f6", color: "#fff", boxShadow: "0 4px 14px rgba(59,130,246,0.3)" },
purple: { background: "#8b5cf6", color: "#fff", boxShadow: "0 4px 14px rgba(139,92,246,0.3)" },
emerald: { background: "#10b981", color: "#fff", boxShadow: "0 4px 14px rgba(16,185,129,0.3)" },
rose: { background: "#f43f5e", color: "#fff", boxShadow: "0 4px 14px rgba(244,63,94,0.3)" },
dark: {
background: "#1e293b",
color: "#fff",
border: "1px solid #334155",
boxShadow: "0 4px 14px rgba(0,0,0,0.3)",
},
outline: { background: "transparent", color: "#94a3b8", border: "1.5px solid #334155" },
};
function btnStyle(v, size = "md") {
const sizes = {
sm: { padding: "0.625rem 1.5rem", fontSize: "0.8125rem" },
md: { padding: "0.875rem 2rem", fontSize: "0.9375rem" },
lg: { padding: "1.125rem 2.75rem", fontSize: "1.0625rem" },
};
return {
position: "relative",
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
borderRadius: "10px",
fontWeight: 600,
cursor: "pointer",
border: "none",
outline: "none",
overflow: "hidden",
transition: "transform 0.2s ease, filter 0.2s ease",
...sizes[size],
...variants[v],
};
}
</script>
<template>
<div style="min-height:100vh;background:#0a0a0a;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2rem;padding:2rem;font-family:system-ui,-apple-system,sans-serif">
<h2 style="font-size:1.5rem;font-weight:700;color:#e2e8f0">Shimmer Buttons</h2>
<p style="color:#525252;font-size:0.875rem">Watch the light sweep across each button</p>
<div style="display:flex;flex-wrap:wrap;gap:2rem;justify-content:center">
<button v-for="[v,label] in [['blue','Discover More'],['purple','Upgrade Plan'],['dark','Learn More']]" :key="v" :style="btnStyle(v)" @mouseenter="e => { e.currentTarget.style.transform='translateY(-1px)'; e.currentTarget.style.filter='brightness(1.1)' }" @mouseleave="e => { e.currentTarget.style.transform='translateY(0)'; e.currentTarget.style.filter='brightness(1)' }">
<span class="shimmer-sweep"></span><span style="position:relative;z-index:1">{{ label }}</span>
</button>
</div>
<div style="display:flex;flex-wrap:wrap;gap:2rem;justify-content:center">
<button :style="btnStyle('emerald','lg')"><span class="shimmer-sweep"></span><span style="position:relative;z-index:1">Get Started Free</span></button>
<button :style="btnStyle('rose','sm')"><span class="shimmer-sweep"></span><span style="position:relative;z-index:1">Buy Now</span></button>
</div>
</div>
</template>
<style scoped>
@keyframes shimmer-sweep { 0% { left: -100%; } 50%, 100% { left: 100%; } }
.shimmer-sweep { position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(120deg,transparent 0%,transparent 30%,rgba(255,255,255,0.25) 45%,rgba(255,255,255,0.4) 50%,rgba(255,255,255,0.25) 55%,transparent 70%,transparent 100%);animation:shimmer-sweep 3s ease-in-out infinite;pointer-events:none; }
</style><script>
const variants = {
blue: { background: "#3b82f6", color: "#fff", boxShadow: "0 4px 14px rgba(59,130,246,0.3)" },
purple: { background: "#8b5cf6", color: "#fff", boxShadow: "0 4px 14px rgba(139,92,246,0.3)" },
emerald: { background: "#10b981", color: "#fff", boxShadow: "0 4px 14px rgba(16,185,129,0.3)" },
rose: { background: "#f43f5e", color: "#fff", boxShadow: "0 4px 14px rgba(244,63,94,0.3)" },
dark: {
background: "#1e293b",
color: "#fff",
border: "1px solid #334155",
boxShadow: "0 4px 14px rgba(0,0,0,0.3)",
},
outline: { background: "transparent", color: "#94a3b8", border: "1.5px solid #334155" },
};
function getStyle(variant) {
const v = variants[variant] || variants.blue;
return Object.entries(v)
.map(([k, val]) => `${k.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase())}:${val}`)
.join(";");
}
</script>
<div style="min-height:100vh;background:#0a0a0a;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2rem;padding:2rem;font-family:system-ui,-apple-system,sans-serif">
<h2 style="font-size:1.5rem;font-weight:700;color:#e2e8f0">Shimmer Buttons</h2>
<p style="color:#525252;font-size:0.875rem">Watch the light sweep across each button</p>
<div style="display:flex;flex-wrap:wrap;gap:2rem;justify-content:center">
{#each [['blue','Discover More'],['purple','Upgrade Plan'],['dark','Learn More']] as [v,label]}
<button class="shimmer-btn" style="position:relative;display:inline-flex;align-items:center;justify-content:center;border-radius:10px;font-weight:600;letter-spacing:0.01em;cursor:pointer;border:none;outline:none;overflow:hidden;padding:0.875rem 2rem;font-size:0.9375rem;{getStyle(v)}">
<span class="shimmer-sweep"></span>
<span style="position:relative;z-index:1">{label}</span>
</button>
{/each}
</div>
<div style="display:flex;flex-wrap:wrap;gap:2rem;justify-content:center">
<button class="shimmer-btn" style="position:relative;display:inline-flex;align-items:center;justify-content:center;border-radius:10px;font-weight:600;cursor:pointer;border:none;overflow:hidden;padding:1.125rem 2.75rem;font-size:1.0625rem;{getStyle('emerald')}">
<span class="shimmer-sweep"></span><span style="position:relative;z-index:1">Get Started Free</span>
</button>
<button class="shimmer-btn" style="position:relative;display:inline-flex;align-items:center;justify-content:center;border-radius:10px;font-weight:600;cursor:pointer;border:none;overflow:hidden;padding:0.625rem 1.5rem;font-size:0.8125rem;{getStyle('rose')}">
<span class="shimmer-sweep"></span><span style="position:relative;z-index:1">Buy Now</span>
</button>
</div>
</div>
<style>
@keyframes shimmer-sweep { 0% { left: -100%; } 50%, 100% { left: 100%; } }
.shimmer-sweep {
position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(120deg, transparent 0%, transparent 30%, rgba(255,255,255,0.25) 45%, rgba(255,255,255,0.4) 50%, rgba(255,255,255,0.25) 55%, transparent 70%, transparent 100%);
animation: shimmer-sweep 3s ease-in-out infinite; pointer-events: none;
}
.shimmer-btn:hover { transform: translateY(-1px); filter: brightness(1.1); }
.shimmer-btn { transition: transform 0.2s ease, filter 0.2s ease; }
</style>Shimmer Button
A button with a periodic shimmering light that sweeps across its surface, creating an eye-catching and polished effect reminiscent of premium UI components.
How it works
- A
::beforepseudo-element is positioned over the button with a diagonal linear gradient - The gradient has a narrow transparent-white-transparent band
@keyframes shimmertranslates this pseudo-element from left to right across the button- The animation repeats on a delay, creating a periodic sweep
Customization
- Speed: Adjust
animation-durationand delay in the keyframes - Color: Change the gradient white band to any color for tinted shimmers
- Angle: Rotate the gradient for different sweep directions
When to use it
- Premium CTA buttons
- Loading state indicators on buttons
- Featured product action buttons