Colour · gradient recipeCSS gradient button — with a hover effect

The button’s background is twice as wide as the button and slides smoothly on hover. A gradient cannot be animated between values, but the background position can.

TextButtonBorderAnimation← Back to the builder
01Example02Code03Steps04Mistakes05Questions06Recipes07Related
01

Live example

change the colours — the code below follows
hover — the gradient slides
Recipe settings
Colours
#6C8CFF0%
#B18CFF100%
White label: worst point 2.6:1 — unreadable
Open in the builder →
02

Ready code

background-position is animated, not the gradient itself
.gradient-button {
  color: #fff;
  background: #6c8cff; /* fallback */
  background: linear-gradient(90deg, #6c8cff, #b18cff, #6c8cff);
  background-size: 200% 100%;
  background-position: 0% 50%;
  border: none;
  border-radius: 10px;
  padding: 16px 28px;
  transition: background-position .4s ease;
}

.gradient-button:hover {
  background-position: 100% 50%;
}

.gradient-button:focus-visible {
  outline: 3px solid #16130f;
  outline-offset: 3px;
}
03

Step by step

  1. 01
    background: linear-gradient(a, b, a)
    Repeat the first colour at the end so the shift is seamless.
  2. 02
    background-size: 200% 100%
    Make the background twice as wide as the button — only half is visible.
  3. 03
    :hover { background-position: 100% 50% }
    Shift the background on hover; transition makes it smooth.
  4. 04
    :focus-visible { outline: … }
    Keep a visible focus for keyboard users — the gradient does not replace it.
04

Common mistakes

transition on background does nothing

Browsers cannot morph one gradient into another. Animate background-position or the opacity of a pseudo-element.

Label unreadable at the light end

White text passes on the dark half and fails on the light one. Check contrast along the whole length — the tool does it on the right.

outline removed

outline: none without a replacement leaves keyboard users without focus — a WCAG 2.4.7 failure.
05

Frequently asked

The transition property cannot morph one gradient into another — the background swaps instantly. Two techniques work. The first makes the background twice as wide as the button and moves background-position, as in the recipe code. The second puts the second gradient on a ::before pseudo-element and fades its opacity from zero to one. The first is simpler; the second lets you move to completely different colours.
06

Other recipes

Updated

«» added to favorites