22 CSS Gradient Buttons04 / 22
CSS Gradient Border Button
Transparent-body buttons with multi-color gradient outlines via the double-background background-clip trick, including an orbiting conic variant animated through @property.
Published
The code
<div class="gb-04">
<div class="gb-04__panel">
<h3 class="gb-04__h">Gradient borders, zero images</h3>
<p class="gb-04__p">Transparent-body buttons with a multi-colour outline — the classic <em>background-clip</em> trick, plus an orbiting conic variant.</p>
<div class="gb-04__row">
<button class="gb-04__btn" type="button">Static border</button>
<button class="gb-04__btn gb-04__btn--orbit" type="button">Orbiting border</button>
</div>
<p class="gb-04__foot">Hover the orbit button — the conic angle accelerates</p>
</div>
</div><div class="gb-04">
<div class="gb-04__panel">
<h3 class="gb-04__h">Gradient borders, zero images</h3>
<p class="gb-04__p">Transparent-body buttons with a multi-colour outline — the classic <em>background-clip</em> trick, plus an orbiting conic variant.</p>
<div class="gb-04__row">
<button class="gb-04__btn" type="button">Static border</button>
<button class="gb-04__btn gb-04__btn--orbit" type="button">Orbiting border</button>
</div>
<p class="gb-04__foot">Hover the orbit button — the conic angle accelerates</p>
</div>
</div>.gb-04,
.gb-04 *,
.gb-04 *::before,
.gb-04 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gb-04 ::selection {
background: #22d3ee;
color: #0b1020;
}
@property --gb-04-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.gb-04 {
--cyan: #22d3ee;
--violet: #a78bfa;
--pink: #f472b6;
--bg: #0b1020;
--panel: #111832;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
background: radial-gradient(800px 400px at 80% -10%,rgba(167,139,250,.12),transparent 60%), radial-gradient(700px 400px at 10% 110%,rgba(34,211,238,.1),transparent 60%), var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 48px 24px;
}
.gb-04__panel {
width: 100%;
max-width: 440px;
background: var(--panel);
border: 1px solid rgba(255,255,255,.06);
border-radius: 20px;
padding: 40px 36px;
text-align: center;
}
.gb-04__h {
color: #e7ecff;
font-size: 22px;
font-weight: 800;
letter-spacing: -.3px;
margin-bottom: 8px;
}
.gb-04__p {
color: #8b93b8;
font-size: 14px;
line-height: 1.6;
margin-bottom: 30px;
}
.gb-04__row {
display: flex;
gap: 18px;
justify-content: center;
flex-wrap: wrap;
}
/* Technique A — double background + background-clip:
layer 1 (padding-box) paints the dark fill, layer 2 (border-box)
paints the gradient that shows through the transparent border. */
.gb-04__btn {
padding: 15px 30px;
border: 2px solid transparent;
border-radius: 14px;
font-family: inherit;
font-size: 15px;
font-weight: 700;
color: #e7ecff;
cursor: pointer;
background: linear-gradient(var(--panel),var(--panel)) padding-box, linear-gradient(120deg,var(--cyan),var(--violet) 55%,var(--pink)) border-box;
transition: color .3s ease,box-shadow .35s ease,transform .25s ease;
-webkit-tap-highlight-color: transparent;
}
.gb-04__btn:hover {
color: #fff;
transform: translateY(-2px);
box-shadow: 0 12px 30px -12px rgba(167,139,250,.55);
}
.gb-04__btn:active {
transform: translateY(0);
}
.gb-04__btn:focus-visible {
outline: 3px solid var(--cyan);
outline-offset: 3px;
}
/* Technique B — animated conic border driven by @property so the
angle itself interpolates and the gradient orbits the button. */
.gb-04__btn--orbit {
background: linear-gradient(var(--panel),var(--panel)) padding-box, conic-gradient(from var(--gb-04-angle),var(--cyan),var(--violet),var(--pink),var(--cyan)) border-box;
animation: gb-04-spin 3.5s linear infinite;
}
@keyframes gb-04-spin {
to {
--gb-04-angle: 360deg;
}
}
.gb-04__btn--orbit:hover {
animation-duration: 1.2s;
box-shadow: 0 12px 34px -10px rgba(244,114,182,.55);
}
.gb-04__foot {
margin-top: 24px;
font-size: 12.5px;
color: #5d6690;
}
@media (prefers-reduced-motion: reduce) {
.gb-04__btn {
transition: none;
}
.gb-04__btn--orbit {
animation: none;
}
.gb-04__btn:hover {
transform: none;
}
}.gb-04,
.gb-04 *,
.gb-04 *::before,
.gb-04 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gb-04 ::selection {
background: #22d3ee;
color: #0b1020;
}
@property --gb-04-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.gb-04 {
--cyan: #22d3ee;
--violet: #a78bfa;
--pink: #f472b6;
--bg: #0b1020;
--panel: #111832;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
background: radial-gradient(800px 400px at 80% -10%,rgba(167,139,250,.12),transparent 60%), radial-gradient(700px 400px at 10% 110%,rgba(34,211,238,.1),transparent 60%), var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 48px 24px;
}
.gb-04__panel {
width: 100%;
max-width: 440px;
background: var(--panel);
border: 1px solid rgba(255,255,255,.06);
border-radius: 20px;
padding: 40px 36px;
text-align: center;
}
.gb-04__h {
color: #e7ecff;
font-size: 22px;
font-weight: 800;
letter-spacing: -.3px;
margin-bottom: 8px;
}
.gb-04__p {
color: #8b93b8;
font-size: 14px;
line-height: 1.6;
margin-bottom: 30px;
}
.gb-04__row {
display: flex;
gap: 18px;
justify-content: center;
flex-wrap: wrap;
}
/* Technique A — double background + background-clip:
layer 1 (padding-box) paints the dark fill, layer 2 (border-box)
paints the gradient that shows through the transparent border. */
.gb-04__btn {
padding: 15px 30px;
border: 2px solid transparent;
border-radius: 14px;
font-family: inherit;
font-size: 15px;
font-weight: 700;
color: #e7ecff;
cursor: pointer;
background: linear-gradient(var(--panel),var(--panel)) padding-box, linear-gradient(120deg,var(--cyan),var(--violet) 55%,var(--pink)) border-box;
transition: color .3s ease,box-shadow .35s ease,transform .25s ease;
-webkit-tap-highlight-color: transparent;
}
.gb-04__btn:hover {
color: #fff;
transform: translateY(-2px);
box-shadow: 0 12px 30px -12px rgba(167,139,250,.55);
}
.gb-04__btn:active {
transform: translateY(0);
}
.gb-04__btn:focus-visible {
outline: 3px solid var(--cyan);
outline-offset: 3px;
}
/* Technique B — animated conic border driven by @property so the
angle itself interpolates and the gradient orbits the button. */
.gb-04__btn--orbit {
background: linear-gradient(var(--panel),var(--panel)) padding-box, conic-gradient(from var(--gb-04-angle),var(--cyan),var(--violet),var(--pink),var(--cyan)) border-box;
animation: gb-04-spin 3.5s linear infinite;
}
@keyframes gb-04-spin {
to {
--gb-04-angle: 360deg;
}
}
.gb-04__btn--orbit:hover {
animation-duration: 1.2s;
box-shadow: 0 12px 34px -10px rgba(244,114,182,.55);
}
.gb-04__foot {
margin-top: 24px;
font-size: 12.5px;
color: #5d6690;
}
@media (prefers-reduced-motion: reduce) {
.gb-04__btn {
transition: none;
}
.gb-04__btn--orbit {
animation: none;
}
.gb-04__btn:hover {
transform: none;
}
}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: CSS Gradient Border Button
Source: https://codefronts.com/components/css-gradient-buttons/css-gradient-border-button/
Transparent-body buttons with multi-color gradient outlines via the double-background background-clip trick, including an orbiting conic variant animated through @property.
## HTML
```html
<div class="gb-04">
<div class="gb-04__panel">
<h3 class="gb-04__h">Gradient borders, zero images</h3>
<p class="gb-04__p">Transparent-body buttons with a multi-colour outline — the classic <em>background-clip</em> trick, plus an orbiting conic variant.</p>
<div class="gb-04__row">
<button class="gb-04__btn" type="button">Static border</button>
<button class="gb-04__btn gb-04__btn--orbit" type="button">Orbiting border</button>
</div>
<p class="gb-04__foot">Hover the orbit button — the conic angle accelerates</p>
</div>
</div>
```
## CSS
```css
.gb-04,
.gb-04 *,
.gb-04 *::before,
.gb-04 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gb-04 ::selection {
background: #22d3ee;
color: #0b1020;
}
@property --gb-04-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.gb-04 {
--cyan: #22d3ee;
--violet: #a78bfa;
--pink: #f472b6;
--bg: #0b1020;
--panel: #111832;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
background: radial-gradient(800px 400px at 80% -10%,rgba(167,139,250,.12),transparent 60%), radial-gradient(700px 400px at 10% 110%,rgba(34,211,238,.1),transparent 60%), var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 48px 24px;
}
.gb-04__panel {
width: 100%;
max-width: 440px;
background: var(--panel);
border: 1px solid rgba(255,255,255,.06);
border-radius: 20px;
padding: 40px 36px;
text-align: center;
}
.gb-04__h {
color: #e7ecff;
font-size: 22px;
font-weight: 800;
letter-spacing: -.3px;
margin-bottom: 8px;
}
.gb-04__p {
color: #8b93b8;
font-size: 14px;
line-height: 1.6;
margin-bottom: 30px;
}
.gb-04__row {
display: flex;
gap: 18px;
justify-content: center;
flex-wrap: wrap;
}
/* Technique A — double background + background-clip:
layer 1 (padding-box) paints the dark fill, layer 2 (border-box)
paints the gradient that shows through the transparent border. */
.gb-04__btn {
padding: 15px 30px;
border: 2px solid transparent;
border-radius: 14px;
font-family: inherit;
font-size: 15px;
font-weight: 700;
color: #e7ecff;
cursor: pointer;
background: linear-gradient(var(--panel),var(--panel)) padding-box, linear-gradient(120deg,var(--cyan),var(--violet) 55%,var(--pink)) border-box;
transition: color .3s ease,box-shadow .35s ease,transform .25s ease;
-webkit-tap-highlight-color: transparent;
}
.gb-04__btn:hover {
color: #fff;
transform: translateY(-2px);
box-shadow: 0 12px 30px -12px rgba(167,139,250,.55);
}
.gb-04__btn:active {
transform: translateY(0);
}
.gb-04__btn:focus-visible {
outline: 3px solid var(--cyan);
outline-offset: 3px;
}
/* Technique B — animated conic border driven by @property so the
angle itself interpolates and the gradient orbits the button. */
.gb-04__btn--orbit {
background: linear-gradient(var(--panel),var(--panel)) padding-box, conic-gradient(from var(--gb-04-angle),var(--cyan),var(--violet),var(--pink),var(--cyan)) border-box;
animation: gb-04-spin 3.5s linear infinite;
}
@keyframes gb-04-spin {
to {
--gb-04-angle: 360deg;
}
}
.gb-04__btn--orbit:hover {
animation-duration: 1.2s;
box-shadow: 0 12px 34px -10px rgba(244,114,182,.55);
}
.gb-04__foot {
margin-top: 24px;
font-size: 12.5px;
color: #5d6690;
}
@media (prefers-reduced-motion: reduce) {
.gb-04__btn {
transition: none;
}
.gb-04__btn--orbit {
animation: none;
}
.gb-04__btn:hover {
transform: none;
}
}
```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: CSS Gradient Border Button
Source: https://codefronts.com/components/css-gradient-buttons/css-gradient-border-button/
Transparent-body buttons with multi-color gradient outlines via the double-background background-clip trick, including an orbiting conic variant animated through @property.
## HTML
```html
<div class="gb-04">
<div class="gb-04__panel">
<h3 class="gb-04__h">Gradient borders, zero images</h3>
<p class="gb-04__p">Transparent-body buttons with a multi-colour outline — the classic <em>background-clip</em> trick, plus an orbiting conic variant.</p>
<div class="gb-04__row">
<button class="gb-04__btn" type="button">Static border</button>
<button class="gb-04__btn gb-04__btn--orbit" type="button">Orbiting border</button>
</div>
<p class="gb-04__foot">Hover the orbit button — the conic angle accelerates</p>
</div>
</div>
```
## CSS
```css
.gb-04,
.gb-04 *,
.gb-04 *::before,
.gb-04 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gb-04 ::selection {
background: #22d3ee;
color: #0b1020;
}
@property --gb-04-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.gb-04 {
--cyan: #22d3ee;
--violet: #a78bfa;
--pink: #f472b6;
--bg: #0b1020;
--panel: #111832;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
background: radial-gradient(800px 400px at 80% -10%,rgba(167,139,250,.12),transparent 60%), radial-gradient(700px 400px at 10% 110%,rgba(34,211,238,.1),transparent 60%), var(--bg);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 48px 24px;
}
.gb-04__panel {
width: 100%;
max-width: 440px;
background: var(--panel);
border: 1px solid rgba(255,255,255,.06);
border-radius: 20px;
padding: 40px 36px;
text-align: center;
}
.gb-04__h {
color: #e7ecff;
font-size: 22px;
font-weight: 800;
letter-spacing: -.3px;
margin-bottom: 8px;
}
.gb-04__p {
color: #8b93b8;
font-size: 14px;
line-height: 1.6;
margin-bottom: 30px;
}
.gb-04__row {
display: flex;
gap: 18px;
justify-content: center;
flex-wrap: wrap;
}
/* Technique A — double background + background-clip:
layer 1 (padding-box) paints the dark fill, layer 2 (border-box)
paints the gradient that shows through the transparent border. */
.gb-04__btn {
padding: 15px 30px;
border: 2px solid transparent;
border-radius: 14px;
font-family: inherit;
font-size: 15px;
font-weight: 700;
color: #e7ecff;
cursor: pointer;
background: linear-gradient(var(--panel),var(--panel)) padding-box, linear-gradient(120deg,var(--cyan),var(--violet) 55%,var(--pink)) border-box;
transition: color .3s ease,box-shadow .35s ease,transform .25s ease;
-webkit-tap-highlight-color: transparent;
}
.gb-04__btn:hover {
color: #fff;
transform: translateY(-2px);
box-shadow: 0 12px 30px -12px rgba(167,139,250,.55);
}
.gb-04__btn:active {
transform: translateY(0);
}
.gb-04__btn:focus-visible {
outline: 3px solid var(--cyan);
outline-offset: 3px;
}
/* Technique B — animated conic border driven by @property so the
angle itself interpolates and the gradient orbits the button. */
.gb-04__btn--orbit {
background: linear-gradient(var(--panel),var(--panel)) padding-box, conic-gradient(from var(--gb-04-angle),var(--cyan),var(--violet),var(--pink),var(--cyan)) border-box;
animation: gb-04-spin 3.5s linear infinite;
}
@keyframes gb-04-spin {
to {
--gb-04-angle: 360deg;
}
}
.gb-04__btn--orbit:hover {
animation-duration: 1.2s;
box-shadow: 0 12px 34px -10px rgba(244,114,182,.55);
}
.gb-04__foot {
margin-top: 24px;
font-size: 12.5px;
color: #5d6690;
}
@media (prefers-reduced-motion: reduce) {
.gb-04__btn {
transition: none;
}
.gb-04__btn--orbit {
animation: none;
}
.gb-04__btn:hover {
transform: none;
}
}
```How this works
The core trick paints two backgrounds on one element: linear-gradient(var(--panel), var(--panel)) padding-box fills the interior with the panel color, while linear-gradient(120deg, var(--cyan), var(--violet), var(--pink)) border-box paints the full box including the border area. With border: 2px solid transparent, the gradient shows through only in that 2px ring — no pseudo-elements, no overflow hacks.
The animated variant swaps the ring layer for conic-gradient(from var(--gb-04-angle), ...) and registers the angle with @property --gb-04-angle { syntax: "<angle>" }. Because registered properties interpolate, a simple keyframe to 360deg makes the gradient orbit the border continuously; hover shortens animation-duration from 3.5s to 1.2s so it visibly accelerates.
Make it yours
- Thicken the ring by raising
border: 2px— the gradient fills whatever border width you give it, and 3–4px reads well on dark UIs. - The interior color must match the surface behind the button; update the first
padding-boxgradient whenever the card background changes or you'll see a halo seam. - Reverse the orbit direction with
animation-direction: reverse, or start it elsewhere by changing thefromangle offset. - For a hover-only orbit, set
animation-play-state: pausedat rest andrunningon hover instead of swapping durations. - Round it into a pill by pairing
border-radius: 999px— the clipped gradient follows any radius for free.
Gotchas — read before shipping
- Setting a shorthand
backgroundlater in the cascade wipes both layers at once — override colors via custom properties, not by re-declaringbackground. - Without
@propertyregistration the conic angle snaps instead of tweening; Firefox shipped it in 128, so provide the static border as the graceful floor for older versions. - The interior fill is opaque by necessity — if you need true see-through glass inside the ring, this trick can't do it; switch to a masked pseudo-element approach instead.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 85+ | 16.4+ | 128+ | 85+ |
Support gated by @property for the orbit; the static double-background border works back to Chrome 22-era syntax.