The short version
- A premium gradient button usually blends two neighbouring hues at similar lightness, with a faint highlight along its top edge.
- Gradients cannot transition, so a smooth hover moves an oversized gradient with background-position or fades an overlay with opacity.
- White text on a gradient button needs at least 4.5:1 contrast against the lightest part of the gradient, not just the darkest.
- A pressed state can be as simple as shifting the button down one pixel and removing its outer shadow.
- Gradient buttons work best as the single primary action on a screen, with secondary actions kept flat or outlined.
On this page
Writing gradient button CSS that looks premium comes down to restraint. Pick two neighbouring hues at a similar lightness, add a faint highlight along the top edge, move the gradient on hover instead of swapping it, and check that the text reads against the lightest part. The loud, rainbow-edged version is easy to make and easy to spot as a template; the quiet version is what makes a product feel finished.
.button {
display: inline-flex;
align-items: center;
gap: 0.5em;
padding: 0.75em 1.4em;
border: 0;
border-radius: 999px;
color: #fff;
font-weight: 600;
background-color: #4f46e5;
background-image: linear-gradient(110deg, #4f46e5, #9333ea 50%, #4f46e5);
background-size: 200% 100%;
background-position: 0% 50%;
box-shadow:
inset 0 1px 0 rgb(255 255 255 / 0.25),
0 6px 16px -6px rgb(79 70 229 / 0.6);
transition: background-position 0.5s ease, transform 0.15s ease, box-shadow 0.15s ease;
cursor: pointer;
}
.button:hover {
background-position: 100% 50%;
}
.button:active {
transform: translateY(1px);
box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.2);
}linear-gradient(110deg, #4f46e5, #9333ea 50%, #4f46e5)Subtle versus loud gradient buttons
A subtle button uses two hues that sit next to each other on the colour wheel, such as indigo and purple, so the gradient reads as depth rather than decoration. A loud button spans distant hues and becomes the most colourful thing on the page. Loud can work for a single launch moment or a playful brand; subtle works everywhere else. Every palette below keeps white text above 4.5:1 at both ends.
Text contrast on gradient buttons
A contrast checker takes one background colour, but a button has a range. Check the text colour against the lightest stop, because that is where the label is weakest. Normal-size button text needs 4.5:1 under WCAG, and WebAIM's contrast checker makes each stop a quick check. The usual failure is a warm gradient ending in yellow or light orange, which looks energetic and leaves half the label unreadable.
Avoid
- Orange to yellow, #f97316 to #fbbf24, under white text: 2.8 and 1.7 to 1
- Light pastel gradients with white labels
- Checking only the colour behind the first letter
- Thin, light font weights on a busy gradient
Do
- Deep stops at similar lightness, like crimson to burnt orange
- Dark text on pastel gradients instead
- Check the lightest stop and the midpoint
- Weights of 600 or more for labels on gradients
More on the maths and the thresholds is in colour contrast and accessibility, and the same rule applies to any text on a gradient background.
Smooth hover states for gradient buttons
background-image does not transition: swap one gradient for another on hover and it snaps. There are two smooth alternatives. The first, used in the recipe above, is to paint the gradient twice as wide and slide background-position. The second is to put the hover gradient on a pseudo-element and fade its opacity, which suits hovers that change colour completely.
.button--fade {
position: relative;
isolation: isolate;
overflow: hidden;
background-image: linear-gradient(110deg, #be123c, #c2410c);
}
.button--fade::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
background-image: linear-gradient(110deg, #c2410c, #be123c);
opacity: 0;
transition: opacity 0.3s ease;
}
.button--fade:hover::before {
opacity: 1;
}Keep hover changes small. A gradient that shifts a little and a shadow that deepens slightly feel responsive; a button that changes hue entirely feels unstable. If you add continuous motion, such as a slow shimmer, turn it off for people who prefer reduced motion.
Borders, outlines and secondary buttons
One gradient button per screen is usually right: it marks the primary action. Secondary actions look better in an outlined style that echoes the gradient in a thin edge. Two backgrounds, one clipped to the padding box and one to the border box, give a rounded gradient outline with a solid middle.
.button--outline {
border: 2px solid transparent;
border-radius: 999px;
color: #312e81;
background:
linear-gradient(#fff, #fff) padding-box,
linear-gradient(110deg, #4f46e5, #9333ea) border-box;
}Disabled and loading states
A disabled gradient button should stop looking like an invitation. Remove the gradient entirely rather than just lowering opacity, which can leave a faded, still-colourful button that people try to press. A flat, low-contrast grey with cursor: not-allowed reads clearly as unavailable. For loading, keep the gradient and swap the label for a spinner so the button does not jump in size.
.button:disabled {
background-image: none;
background-color: #e5e7eb;
color: #6b7280;
box-shadow: none;
cursor: not-allowed;
}Finishing touches that read as premium
- A top highlight.
inset 0 1px 0 rgb(255 255 255 / 0.25)suggests a light source above and gives the surface a slight curve. - A tinted shadow. Shadow in the button's own hue, rather than black, makes it glow instead of float.
- One angle for everything. Use the same gradient angle, such as 110deg, on every gradient control.
- Brand colours, not presets. The blend should come from your palette; gradient branding explains why.
- A conic sheen, sparingly. A faint conic layer can add a metallic glint; see CSS conic gradients.
Questions people ask
How do I make a gradient button in CSS?
Set background-image: linear-gradient(110deg, #4f46e5, #9333ea) on the button, with white text, rounded corners and a solid background-color fallback.
How do I animate a gradient button on hover?
Make the gradient twice as wide with background-size: 200% 100% and transition background-position, or fade a pseudo-element holding the hover gradient.
Why does my gradient button change instantly on hover?
Browsers cannot transition between two background-image values. Move or fade the gradient instead of replacing it.
What text colour works on a gradient button?
Whichever colour reaches at least 4.5:1 contrast against the lightest part of the gradient. White works on deep gradients; dark text suits pastels.
Should every button use a gradient?
No. Use a gradient for the single primary action on a screen and keep secondary buttons flat or outlined, so the important one stands out.
Written by Gradiently
The team behind Gradiently, a design tool built around Marks: living gradients that make everything you design look like yours.
See our profile


