Hover✨ Premium

Border Gradient

A 2 px indigo-to-violet gradient border fades in on hover using two stacked pseudo-elements — no transform, pure CSS.

CSSBorder

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Hover has 48 effects, including 5 free. Explore the category →

3 usage examples

Pricing card for invoicing software — landing page for tradespeople — Border Gradient example 1

① Pricing card for invoicing software — landing page for tradespeople

WhenThree pricing columns (Starter, Pro, Team) on a dark background; on hover the most-viewed card gains a gradient indigo-violet border.
WhyA glowing border highlights the plan without changing the layout (no overflowing box-shadow), which is hard to achieve in CSS without this technique.
Settings280×360 px cards on dark background; hover area covering the capture ellipse; pricing text and CTA button in each card.
Skill badge on an interactive CV — online CV builder — Border Gradient example 2

② Skill badge on an interactive CV — online CV builder

WhenA grid of skills (Python, Figma, SQL…) as small 120×80 px cards; on hover a gradient border highlights the skill.
WhyA gradient border on a dark background resembles a technical badge; it doesn't weigh down the card the way a coloured box-shadow would.
SettingsTen cards in a tight grid; 2 px border, 8 px corner radius; targets on the capture ellipse.
Jewellery collection thumbnail — boutique for an artisan jeweller — Border Gradient example 3

③ Jewellery collection thumbnail — boutique for an artisan jeweller

WhenJewellery photos in a grid on a near-black background; on hover the photo gains a golden border (colours: gold → pink).
WhyA golden frame around jewellery is a recognisable luxury visual cue, requiring neither text-decoration nor transform.
Settings300×300 px photos; gradient replaced with linear-gradient(135deg, #d4af37, #f7c6a8); inset widened to -3px for a more generous border.

How it works

The .fx-0345-root wrapper centres a 200 px button. The technique uses two pseudo-elements: ::before places a gradient background (135°, indigo → violet) in negative (inset: -2px) behind the element, creating a 2 px overhang on all sides; ::after places a solid card-colour background in positive (inset: 2px), masking the interior. At rest, ::before is at opacity: 0. On hover, it transitions to 1 over 0.3 s. The gradient-border illusion works because only the 2 px gap between the two pseudo-elements is visible.

The element itself carries border: 2px solid transparent to reserve space. z-index: -1 on both pseudo-elements places them behind the content. :focus-visible triggers the same ::before opacity as hover, with an indigo outline added. Pure CSS, no JavaScript. Under reduced motion, the transition is disabled but the border appears instantly.

Accessibility

  • Reduced motion: under prefers-reduced-motion: reduce, the opacity transition is disabled. The gradient border appears instantly on hover and focus — state feedback is guaranteed.
  • Keyboard: the element is a natively focusable <button>. :focus-visible triggers the border and adds a 2 px outline offset by 4 px, stacking two visual signals for keyboard focus.
  • Touch: a tap activates the hover state on most mobile browsers. The border stays visible until focus moves.
  • Border contrast: on white backgrounds, the gradient border may lack contrast depending on the colours. Increase the thickness (inset: -3px) or adjust hues to maintain a WCAG ≥ 3:1 ratio against the background.

Browser compatibility

Pure CSS. Properties: ::before/::after, inset shorthand, opacity, transition, negative z-index, :focus-visible. Verified in Chromium and Firefox: border visible, two independent copies, 0 errors. inset shorthand requires Chrome 87+, Firefox 87+, Safari 14.1+.

Chrome 87+✓ Full (measured)
Firefox 87+✓ Full (measured)
Safari 14.1+✓ Full (inset shorthand)
Edge 87+✓ Full (Chromium engine)
Mobile iOS 14.5+✓ Full
Android Chrome 87+✓ Full (measured)

Without inset shorthand (before 2021), use top: -2px; right: -2px; bottom: -2px; left: -2px. Without :focus-visible, keyboard focus does not trigger the border.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0345-root">
  <button class="gbd-box gbd-border" type="button">
    <span>Your text</span>
  </button>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Border colours (CSS — linear-gradient(135deg, #6366f1, #d946ef)) indigo → violet Replace both colours to match your brand. Add intermediate stops for a rainbow effect.
Border thickness (CSS — inset: -2px and inset: 2px) 2 px Switching to -3px and 3px gives a 3 px border. Both values must match in absolute value.
Duration (CSS — 0.3s) 0.3 s 0.15 s is snappier; 0.5 s is softer.
Gradient angle (CSS — 135deg) 135° (diagonal) 90deg gives a horizontal gradient; to right or to bottom are equally readable.
Corner radius of pseudo-element (CSS — calc(var(--radius-xl) + 2px)) card radius + 2 px Use calc() to auto-adjust if you change the card's radius.

FAQ

CSS does not allow border-image combined with border-radius: rounded corners and native gradient borders are incompatible. The two stacked pseudo-elements work around this limitation.
z-index: -1 on the pseudo-elements places them behind the card background. If your card has an explicit positive z-index, add isolation: isolate to the card to create a new stacking context.
Yes, by replacing the opacity transition with a @keyframes that animates background-position on a wider gradient (conic-gradient or large linear gradient). That technique is outside the scope of this effect, which is hover-only.