22 CSS Gradient Buttons18 / 22

Pure CSSMIT licensed

Tailwind Style CSS Gradient Button

A docs-style specimen grid of the four most-loved utility-framework gradient recipes — indigo/purple, cyan/blue, emerald/teal, rose/orange — in pure CSS with hover shade-deepening.

Published

Live Demo
Try it

The code

<div class="gb-18">
  <div class="gb-18__doc">
    <div class="gb-18__dochead">
      <b>Gradient recipes</b>
      <code>bg-gradient-to-r</code>
    </div>
    <div class="gb-18__grid">
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--iris" type="button">Deploy project</button>
        <p class="gb-18__util">from-indigo-500 to-purple-500</p>
      </div>
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--sky" type="button">Invite your team</button>
        <p class="gb-18__util">from-cyan-500 to-blue-500</p>
      </div>
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--mint" type="button">Enable billing</button>
        <p class="gb-18__util">from-emerald-500 to-teal-500</p>
      </div>
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--ember" type="button">Upgrade plan</button>
        <p class="gb-18__util">from-rose-500 to-orange-500</p>
      </div>
    </div>
  </div>
</div>
.gb-18,
.gb-18 *,
.gb-18 *::before,
.gb-18 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.gb-18 ::selection {
  background: #6366f1;
  color: #fff;
}

.gb-18 {
  /* Tailwind-inspired tokens: indigo/purple, cyan/blue, emerald/teal, rose/orange */
  --indigo-500: #6366f1;
  --purple-500: #a855f7;
  --cyan-500: #06b6d4;
  --blue-500: #3b82f6;
  --emerald-500: #10b981;
  --teal-500: #14b8a6;
  --rose-500: #f43f5e;
  --orange-500: #f97316;
  --slate-900: #0f172a;
  --slate-500: #64748b;
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  background: #fff;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
}

.gb-18__doc {
  width: 100%;
  max-width: 520px;
  border: 1px solid #e2e8f0;
  border-radius: 16px;
  overflow: hidden;
}

.gb-18__dochead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
  background: #f8fafc;
  border-bottom: 1px solid #e2e8f0;
}

.gb-18__dochead b {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--slate-900);
}

.gb-18__dochead code {
  font-family: ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size: 11.5px;
  color: var(--slate-500);
  background: #eef2f7;
  padding: 3px 8px;
  border-radius: 6px;
}

.gb-18__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit,minmax(210px,1fr));
  gap: 1px;
  background: #e2e8f0;
}

.gb-18__cell {
  background: #fff;
  padding: 26px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
/* The utility recipe: from/to duotone, shadow-{color}/50, hover
   swaps to deeper shades via a cross-fading ::before layer. */

.gb-18__btn {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 12px 26px;
  border: none;
  border-radius: 10px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  background-image: linear-gradient(to right,var(--from),var(--to));
  box-shadow: 0 10px 22px -8px var(--ring);
  transition: box-shadow .3s ease,transform .2s ease;
  -webkit-tap-highlight-color: transparent;
}

.gb-18__btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: linear-gradient(to right,var(--from-hover),var(--to-hover));
  opacity: 0;
  transition: opacity .3s ease;
}

.gb-18__btn:hover {
  transform: translateY(-1.5px);
  box-shadow: 0 14px 28px -8px var(--ring);
}

.gb-18__btn:hover::before {
  opacity: 1;
}

.gb-18__btn:active {
  transform: translateY(0) scale(.98);
}

.gb-18__btn:focus-visible {
  outline: 3px solid var(--from);
  outline-offset: 3px;
}

.gb-18__btn--iris {
  --from: var(--indigo-500);
  --to: var(--purple-500);
  --from-hover: #4f46e5;
  --to-hover: #9333ea;
  --ring: rgba(99,102,241,.5);
}

.gb-18__btn--sky {
  --from: var(--cyan-500);
  --to: var(--blue-500);
  --from-hover: #0891b2;
  --to-hover: #2563eb;
  --ring: rgba(6,182,212,.5);
}

.gb-18__btn--mint {
  --from: var(--emerald-500);
  --to: var(--teal-500);
  --from-hover: #059669;
  --to-hover: #0d9488;
  --ring: rgba(16,185,129,.5);
}

.gb-18__btn--ember {
  --from: var(--rose-500);
  --to: var(--orange-500);
  --from-hover: #e11d48;
  --to-hover: #ea580c;
  --ring: rgba(244,63,94,.5);
}

.gb-18__util {
  font-family: ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size: 10.5px;
  color: var(--slate-500);
  text-align: center;
  line-height: 1.5;
}

@media (prefers-reduced-motion: reduce) {
  .gb-18__btn,
    .gb-18__btn::before {
    transition: none;
  }

  .gb-18__btn:hover {
    transform: none;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Gradient Button from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Style CSS Gradient Button
Source: https://codefronts.com/components/css-gradient-buttons/tailwind-style-css-gradient-button/

A docs-style specimen grid of the four most-loved utility-framework gradient recipes — indigo/purple, cyan/blue, emerald/teal, rose/orange — in pure CSS with hover shade-deepening.
## HTML
```html
<div class="gb-18">
  <div class="gb-18__doc">
    <div class="gb-18__dochead">
      <b>Gradient recipes</b>
      <code>bg-gradient-to-r</code>
    </div>
    <div class="gb-18__grid">
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--iris" type="button">Deploy project</button>
        <p class="gb-18__util">from-indigo-500 to-purple-500</p>
      </div>
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--sky" type="button">Invite your team</button>
        <p class="gb-18__util">from-cyan-500 to-blue-500</p>
      </div>
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--mint" type="button">Enable billing</button>
        <p class="gb-18__util">from-emerald-500 to-teal-500</p>
      </div>
      <div class="gb-18__cell">
        <button class="gb-18__btn gb-18__btn--ember" type="button">Upgrade plan</button>
        <p class="gb-18__util">from-rose-500 to-orange-500</p>
      </div>
    </div>
  </div>
</div>
```
## CSS
```css
.gb-18,
.gb-18 *,
.gb-18 *::before,
.gb-18 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.gb-18 ::selection {
  background: #6366f1;
  color: #fff;
}

.gb-18 {
  /* Tailwind-inspired tokens: indigo/purple, cyan/blue, emerald/teal, rose/orange */
  --indigo-500: #6366f1;
  --purple-500: #a855f7;
  --cyan-500: #06b6d4;
  --blue-500: #3b82f6;
  --emerald-500: #10b981;
  --teal-500: #14b8a6;
  --rose-500: #f43f5e;
  --orange-500: #f97316;
  --slate-900: #0f172a;
  --slate-500: #64748b;
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  background: #fff;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
}

.gb-18__doc {
  width: 100%;
  max-width: 520px;
  border: 1px solid #e2e8f0;
  border-radius: 16px;
  overflow: hidden;
}

.gb-18__dochead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
  background: #f8fafc;
  border-bottom: 1px solid #e2e8f0;
}

.gb-18__dochead b {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--slate-900);
}

.gb-18__dochead code {
  font-family: ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size: 11.5px;
  color: var(--slate-500);
  background: #eef2f7;
  padding: 3px 8px;
  border-radius: 6px;
}

.gb-18__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit,minmax(210px,1fr));
  gap: 1px;
  background: #e2e8f0;
}

.gb-18__cell {
  background: #fff;
  padding: 26px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
/* The utility recipe: from/to duotone, shadow-{color}/50, hover
   swaps to deeper shades via a cross-fading ::before layer. */

.gb-18__btn {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 12px 26px;
  border: none;
  border-radius: 10px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  background-image: linear-gradient(to right,var(--from),var(--to));
  box-shadow: 0 10px 22px -8px var(--ring);
  transition: box-shadow .3s ease,transform .2s ease;
  -webkit-tap-highlight-color: transparent;
}

.gb-18__btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: linear-gradient(to right,var(--from-hover),var(--to-hover));
  opacity: 0;
  transition: opacity .3s ease;
}

.gb-18__btn:hover {
  transform: translateY(-1.5px);
  box-shadow: 0 14px 28px -8px var(--ring);
}

.gb-18__btn:hover::before {
  opacity: 1;
}

.gb-18__btn:active {
  transform: translateY(0) scale(.98);
}

.gb-18__btn:focus-visible {
  outline: 3px solid var(--from);
  outline-offset: 3px;
}

.gb-18__btn--iris {
  --from: var(--indigo-500);
  --to: var(--purple-500);
  --from-hover: #4f46e5;
  --to-hover: #9333ea;
  --ring: rgba(99,102,241,.5);
}

.gb-18__btn--sky {
  --from: var(--cyan-500);
  --to: var(--blue-500);
  --from-hover: #0891b2;
  --to-hover: #2563eb;
  --ring: rgba(6,182,212,.5);
}

.gb-18__btn--mint {
  --from: var(--emerald-500);
  --to: var(--teal-500);
  --from-hover: #059669;
  --to-hover: #0d9488;
  --ring: rgba(16,185,129,.5);
}

.gb-18__btn--ember {
  --from: var(--rose-500);
  --to: var(--orange-500);
  --from-hover: #e11d48;
  --to-hover: #ea580c;
  --ring: rgba(244,63,94,.5);
}

.gb-18__util {
  font-family: ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size: 10.5px;
  color: var(--slate-500);
  text-align: center;
  line-height: 1.5;
}

@media (prefers-reduced-motion: reduce) {
  .gb-18__btn,
    .gb-18__btn::before {
    transition: none;
  }

  .gb-18__btn:hover {
    transform: none;
  }
}
```

How this works

Each button reproduces the utility idiom bg-gradient-to-r from-X-500 to-Y-500 in vanilla CSS: design tokens named after the Tailwind scale (--indigo-500: #6366f1 etc.) feed linear-gradient(to right, var(--from), var(--to)), and the framework's signature colored shadow (shadow-indigo-500/50) becomes a box-shadow with the from-color at 50% alpha.

The hover behavior mirrors hover:from-indigo-600 without the snap: since gradients can't interpolate, a ::before layer pre-renders the 600-shade pair and crossfades in via opacity — the exact darkening Tailwind specifies, but smooth. Each cell labels its recipe in monospace, making the component read like a living style-guide page.

Make it yours

  • The token layer is the point — extend it with more scale steps (--indigo-600, --indigo-400) and recipes stay one-line edits per modifier class.
  • Reproduce bg-gradient-to-br by swapping to right for 135deg; the utility direction map is just angle names.
  • The 50%-alpha colored ring is what makes these feel "Tailwind" — resist replacing it with a neutral black shadow, which instantly flattens the look.
  • Hover shades here are the real 600-scale hex values, not filter: brightness() — filters shift hue subtly and break the framework-faithful color math.
  • The specimen chrome (header, monospace captions, 1px grid gaps) is copy-paste ready for documenting your own design system's button recipes.

Gotchas — read before shipping

  • Crossfading to the darker pair means the ::before must match the button's border-radius via inset: 0 inside overflow: hidden — a radius mismatch flashes square corners mid-hover.
  • These famous palettes are popular partly because they're contrast-safe with white text at the 500 level — substituting lighter 400-scale stops quietly breaks that guarantee.
  • The auto-fit, minmax(210px, 1fr) grid collapses to one column on narrow screens; if you embed this in a sidebar, the 1px-gap borders need the container background token to stay visible.

Browser support

ChromeSafariFirefoxEdge
57+10.1+52+57+

CSS Grid for the specimen layout is the floor; the buttons themselves work far earlier.

Search CodeFronts

Loading…