Skip to content
Menu

Experiment #002

Glow Button

A blurred layer sits behind the button and fades in on hover or keyboard focus, while the border brightens in sync. The glow is a separate element (or pseudo-element in the CSS variant), so only opacity animates — no repaint-heavy box-shadow transition. Works on light and dark backgrounds with a single accent color.

Scene

Technical details

Experiment
FX-002
Category
Buttons
Stack
Tailwind + CSS
Difficulty
Beginner
Dependencies
none
Weight
HTML 1.0 KB · CSS 1.1 KB
Added
2026-08-21
Updated
2026-08-21

Lab notes

Keep the glow opacity between 0.4 and 0.7 — past that it reads as neon. Tune the spread with the blur radius (8–16px) and the negative inset of the glow layer, not with a larger element.

Take the code

HTML — code.html
<!-- Glow Button — Tailwind CSS -->
<button
    type="button"
    class="group relative rounded-md focus-visible:outline-2 focus-visible:outline-offset-4
           focus-visible:outline-indigo-500"
>
    <!-- Glow layer: sits behind the label, only opacity animates -->
    <span
        aria-hidden="true"
        class="absolute -inset-0.5 rounded-md bg-indigo-500 opacity-0 blur-md
               transition-opacity duration-300 ease-out
               group-hover:opacity-60 group-focus-visible:opacity-60
               motion-reduce:transition-none"
    ></span>

    <!-- Button surface: covers the glow, border brightens in sync -->
    <span
        class="relative flex items-center rounded-md border border-indigo-400/50 bg-indigo-600
               px-7 py-3 text-sm font-medium text-white
               transition-colors duration-300 ease-out
               group-hover:border-indigo-300 group-focus-visible:border-indigo-300
               motion-reduce:transition-none"
    >
        Hover me
    </span>
</button>
CSS — styles.css
/* Glow Button — vanilla CSS */

.glow-button {
    position: relative;
    isolation: isolate;
    display: inline-flex;
    align-items: center;
    padding: 0.75rem 1.75rem;
    border: 1px solid rgb(129 140 248 / 0.5);
    border-radius: 6px;
    background-color: #4f46e5;
    color: #ffffff;
    font: 500 0.875rem / 1.25rem system-ui, sans-serif;
    cursor: pointer;
    transition: border-color 300ms ease-out;
}

/* Glow layer: blurred copy of the button, behind it, only opacity animates */
.glow-button::before {
    content: "";
    position: absolute;
    inset: -2px;
    z-index: -1;
    border-radius: inherit;
    background-color: #6366f1;
    filter: blur(12px);
    opacity: 0;
    transition: opacity 300ms ease-out;
}

.glow-button:hover,
.glow-button:focus-visible {
    border-color: #a5b4fc;
}

.glow-button:hover::before,
.glow-button:focus-visible::before {
    opacity: 0.6;
}

.glow-button:focus-visible {
    outline: 2px solid #6366f1;
    outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
    .glow-button,
    .glow-button::before {
        transition: none;
    }
}

Adjacent

Specimens nearby

All Buttons →
FX-004 Buttons
FX-003 Buttons