CSS gradient button generator
Gradient buttons with a hover that actually animates, a visible focus ring, a pressed state and an automatic check that the label is readable.
Hover, tab to and press the button to see every state.
Label colour #ffffff — worst contrast 4.14:1 (large/bold text only)
.btn-gradient {
display: inline-flex;
align-items: center;
min-height: 44px;
padding: 14px 28px;
border: 0;
border-radius: 999px;
color: #ffffff;
font-weight: 700;
background-color: #b3005f;
background-image: linear-gradient(90deg, #b3005f 0%, #e0470b 50%, #e0470b 50%, #b3005f 100%);
background-size: 200% 100%;
cursor: pointer;
transition: background-position .4s ease, box-shadow .2s ease, transform .15s ease;
}
.btn-gradient:hover {
background-position: 100% 0;
}
.btn-gradient:active { transform: translateY(1px); }
.btn-gradient:focus-visible {
outline: 3px solid #b3005f;
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.btn-gradient { transition: none; }
}Questions
How do I make a gradient button in CSS?
Put the gradient in background-image and keep a solid background-color as fallback. For a smooth hover, make the background 200% wide and shift background-position on :hover — gradients themselves can’t be transitioned directly without @property.
Why doesn’t my gradient transition on hover?
Browsers can’t interpolate between two background-image values, so the change is instant. Either animate background-position on an oversized gradient (what this generator does), fade an overlay pseudo-element, or register custom properties with @property and transition those.
What text colour should a gradient button use?
Whichever passes 4.5:1 against every part of the gradient. The generator checks white and near-black text against the whole gradient and tells you which works.
Do I need a focus style?
Yes. WCAG 2.2 requires a visible focus indicator. Use :focus-visible with a 2–3px outline offset from the button so it shows over any gradient.