Animated gradient borders for React components using SVG-based path-following gradients.
npm install react-gradient-bordersimport { GradientBorder } from 'react-gradient-borders';
function App() {
return (
<GradientBorder
// Appearance
colors={['#0066ff', '#ffdd00']} // default
strokeWidth={3} // default
borderRadius={12} // default
lineCapStart="square" // 'round' | 'square' (default: 'square')
lineCapEnd="square" // 'round' | 'square' (default: 'square')
// Animation
animate={true} // default
duration={2000} // default
animationMode="once" // 'once' | 'loop' (default: 'once')
variant="default" // 'default' | 'split' (default: 'default')
reverse={false} // default
startPosition="top-left" // default
// Trigger
trigger="mount" // 'mount' | 'hover' | 'focus' | 'click' | 'manual'
active={undefined} // for trigger="manual" control
showWhenInactive={false} // default
// Border Position
borderPosition="inner" // 'inner' | 'outer' (default: 'inner')
borderOffset={0} // number | string (default: 0)
// Ants Marching
ants={false} // default
antsDashWidth={20} // default
antsGapWidth={16} // default
antsSpeed={250} // default
// Performance
lazy={true} // default
lazyRootMargin="100px" // default
resizeThrottle={150} // default
segments={200} // default
// Styling
style={{}} // default
className="" // default
>
<div style={{ padding: 24, background: '#1a1a2e', borderRadius: 12 }}>
<h2>Hello World</h2>
<p>Content with an animated gradient border!</p>
</div>
</GradientBorder>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
- | Content to render inside the gradient border |
colors |
string[] |
['#0066ff', '#ffdd00'] |
Array of colors for the gradient |
startPosition |
StartPosition |
'top-left' |
Where the gradient begins drawing from |
strokeWidth |
number |
3 |
Width of the border stroke in pixels |
lineCapStart |
LineCap |
'square' |
Line cap for the start: 'round' or 'square' |
lineCapEnd |
LineCap |
'square' |
Line cap for the end/tip: 'round' or 'square' |
borderRadius |
number |
12 |
Border radius in pixels |
segments |
number |
200 |
Number of segments to divide the border into |
duration |
number |
2000 |
Animation duration in milliseconds |
animate |
boolean |
true |
Whether to animate the border drawing in |
trigger |
Trigger |
'mount' |
What triggers the border to appear |
animationMode |
AnimationMode |
'once' |
Animation behavior: draw once or loop continuously |
variant |
Variant |
'default' |
Animation variant: draw from one point or split from both directions |
reverse |
boolean |
false |
Reverse the animation direction |
active |
boolean |
- | For manual trigger control - whether the border is active |
showWhenInactive |
boolean |
false |
Show border when not triggered (for hover/focus/click modes) |
lazy |
boolean |
true |
Only render when visible in viewport |
lazyRootMargin |
string |
'100px' |
Margin around viewport for lazy loading |
resizeThrottle |
number |
150 |
Throttle interval in ms for resize recalculations |
ants |
boolean |
false |
Enable ants marching (dashed line) effect |
antsDashWidth |
number |
20 |
Width of each dash in pixels |
antsGapWidth |
number |
16 |
Gap between dashes in pixels |
antsSpeed |
number |
250 |
Speed of marching animation in ms per dash cycle |
borderPosition |
BorderPosition |
'inner' |
Border position: 'inner' or 'outer' |
borderOffset |
number | string |
0 |
Offset the border (e.g., 4, "10px", "-5px") |
style |
CSSProperties |
{} |
Additional CSS styles for the container |
className |
string |
'' |
Additional CSS class name for the container |
The trigger prop controls when the border appears:
'mount'(default) - Border appears on component mount'hover'- Border appears on mouse hover'focus'- Border appears when a child element is focused'click'- Border toggles on click'manual'- Control with theactiveprop
The animationMode prop controls how the border animates:
'once'(default) - Draws the border once and stops'loop'- Continuously animates the gradient around the border
The variant prop controls the drawing style:
'default'(default) - Draws from the start position in one direction'split'- Draws from both directions simultaneously, meeting on the opposite side
The borderPosition prop controls where the border is drawn:
'inner'(default) - Border is drawn inside the element bounds'outer'- Border is drawn outside the element bounds
Use borderOffset to fine-tune the position. Positive values move outward, negative values move inward. Accepts numbers (pixels) or CSS length strings like "10px" or "-0.5rem".
The startPosition prop accepts either a preset string or a number from 0-1:
Preset positions:
'top-left'(default) - Starts at top-left corner'top'- Starts at top center'top-right'- Starts at top-right corner'right'- Starts at right center'bottom-right'- Starts at bottom-right corner'bottom'- Starts at bottom center'bottom-left'- Starts at bottom-left corner'left'- Starts at left center
Custom position: Pass a number from 0 to 1 representing a position along the border path (0 = start of path, 1 = end of path).
<GradientBorder colors={['#ff006e', '#8338ec', '#3a86ff', '#00f5d4']}>
<div>Rainbow gradient border</div>
</GradientBorder><GradientBorder
colors={['#ff006e', '#00f5d4']}
startPosition="bottom"
>
<div>Gradient starts from bottom center</div>
</GradientBorder><GradientBorder colors={['#ff006e', '#8338ec']} animate={false}>
<div>Static gradient border</div>
</GradientBorder><GradientBorder
colors={['#9b5de5', '#f15bb5']}
strokeWidth={4}
borderRadius={24}
>
<div>Purple to pink gradient</div>
</GradientBorder><GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff']}
trigger="hover"
duration={800}
>
<div>Border appears on hover</div>
</GradientBorder><GradientBorder
colors={['#4facfe', '#00f2fe', '#43e97b']}
trigger="focus"
duration={600}
>
<input type="text" placeholder="Focus me..." />
</GradientBorder><GradientBorder
colors={['#ff006e', '#8338ec']}
trigger="click"
>
<div>Click to toggle border</div>
</GradientBorder><GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff', '#00f5d4']}
animationMode="loop"
duration={3000}
>
<div>Gradient continuously animates around</div>
</GradientBorder><GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff', '#00f5d4']}
variant="split"
duration={2000}
>
<div>Gradient draws from both directions and meets in the middle</div>
</GradientBorder><GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff']}
ants
animationMode="loop"
>
<div>Marching ants border effect</div>
</GradientBorder><GradientBorder
colors={['#ff006e', '#8338ec']}
borderPosition="outer"
strokeWidth={4}
>
<div>Border drawn outside the element</div>
</GradientBorder><GradientBorder
colors={['#ff006e', '#8338ec']}
borderOffset={8}
>
<div>Border offset 8px outward from inner edge</div>
</GradientBorder>function ControlledBorder() {
const [active, setActive] = useState(false);
return (
<>
<GradientBorder
colors={['#ff006e', '#8338ec']}
trigger="manual"
active={active}
>
<div>Programmatically controlled</div>
</GradientBorder>
<button onClick={() => setActive(!active)}>Toggle</button>
</>
);
}function ReplayableCard() {
const [key, setKey] = useState(0);
return (
<>
<GradientBorder
key={key}
colors={['#ff006e', '#8338ec', '#00f5d4']}
duration={1500}
>
<div>Animated content</div>
</GradientBorder>
<button onClick={() => setKey(k => k + 1)}>
Replay Animation
</button>
</>
);
}The component creates an SVG overlay that draws line segments along a rounded rectangle path. Each segment is colored according to a linear interpolation across all colors in the gradient. When animate is true, segments are progressively revealed to create a drawing effect. The startPosition prop allows you to control where along the border path the gradient begins.
This component uses:
ResizeObserverfor responsive sizingIntersectionObserverfor lazy loadingrequestAnimationFramefor smooth animations
These APIs are supported in all modern browsers.
MIT
