HTML Button animated backgrounds

HTML Button animated backgrounds

~ 5 min read

The approach

Exploring a few animated button background effects on interaction. The basic thought process is to position the button as relative and then animate an absolutely positioned pseudo-element (::before or ::after) within it, often with overflow: hidden on the parent.

The animation trigger is usually hover or active (click), with focus-visible also being styled so keyboard users and touch devices (where hover can be sticky or non-existent) still get visual feedback.

1. Swipe Right

A simple “fill” effect where the background slides in from the left.

The CSS

.btn.swipe {
    --bg-color: #235459;
    --bg-color-hover: #4bb1c0;
    --txt-color: white;
    --animate-duration: 0.3s;

    position: relative;
    overflow: hidden;
    isolation: isolate; /* Creates a new stacking context */
    background-color: var(--bg-color);
    color: var(--txt-color);
    /* ...other styles... */
}

.btn.swipe::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: var(--bg-color-hover);
    transform: translateX(-100%);
    transition: transform var(--animate-duration) cubic-bezier(0.4, 0, 0.2, 1);
}

.btn.swipe:hover::before,
.btn.swipe:focus-visible::before {
    transform: translateX(0);
}

2. Click Circle Expand

This effect creates a ripple-like circle expansion from the center when the button is clicked (active state).

The CSS

.btn.click-circle {
    /* ...variables... */
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.btn.click-circle::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    border-radius: 50%;
    transform: translate(-50%, -50%); /* Center the element */
    z-index: -1;
    background-color: var(--bg-color-hover);
    transition:
        width var(--animate-duration) ease-out,
        height var(--animate-duration) ease-out;
}

.btn.click-circle:active::before,
.btn.click-circle:focus-visible::before {
    width: 250%;
    height: 250%;
}

3. Shutter Up/Down

Two panels “close” from the top and bottom to fill the background.

The CSS

.btn.shutter {
    /* ... */
    position: relative;
    overflow: hidden;
    background-color: transparent;
    color: var(--bg-color);
    /* ... */
}

.btn.shutter::before,
.btn.shutter::after {
    content: "";
    position: absolute;
    left: 0;
    width: 100%;
    height: 50%;
    background-color: var(--bg-color);
    z-index: -1;
    transition: transform 0.25s cubic-bezier(0.77, 0, 0.175, 1);
}

.btn.shutter::before {
    top: 0;
    transform: translateY(-100%);
}

.btn.shutter::after {
    bottom: 0;
    transform: translateY(100%);
}

.btn.shutter:hover::before,
.btn.shutter:focus-visible::before,
.btn.shutter:hover::after,
.btn.shutter:focus-visible::after {
    transform: translateY(0);
}

4. Diagonal Swipe

A variation of the swipe effect where a skewed element slides across, creating a dynamic angle.

The CSS

.btn.diagonal::before {
    content: "";
    position: absolute;
    top: 0;
    left: -20%; /* wider to cover skew */
    width: 140%;
    height: 100%;
    background-color: var(--bg-color-hover);
    transform: skewX(-20deg) translateX(-110%);
    z-index: -1;
    transition: transform 0.35s cubic-bezier(0.3, 1, 0.8, 1);
}

.btn.diagonal:hover::before {
    transform: skewX(-20deg) translateX(0);
}

5. Gradient Glow

Instead of a solid fill, this uses animates a gradient or shadow to create a glowing effect.

The CSS

.btn.glow {
    /* ... */
    transition:
        transform 0.2s ease,
        box-shadow 0.2s ease;
    box-shadow: 0 0 0 0 rgba(75, 177, 192, 0.7);
}

.btn.glow:hover,
.btn.glow:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 4px 20px 0 rgba(75, 177, 192, 0.6);
}

all posts →