react-gradient-borders
v1.0.0
Published
Animated gradient borders for React components with SVG-based path-following gradients
Maintainers
Readme
react-gradient-borders
Animated gradient borders for React components using SVG-based path-following gradients.
Installation
npm install react-gradient-bordersUsage
import { 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>
);
}Props
| 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 |
Trigger
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
AnimationMode
The animationMode prop controls how the border animates:
'once'(default) - Draws the border once and stops'loop'- Continuously animates the gradient around the border
Variant
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
BorderPosition
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".
StartPosition
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).
Examples
Multi-color gradient
<GradientBorder colors={['#ff006e', '#8338ec', '#3a86ff', '#00f5d4']}>
<div>Rainbow gradient border</div>
</GradientBorder>Custom start position
<GradientBorder
colors={['#ff006e', '#00f5d4']}
startPosition="bottom"
>
<div>Gradient starts from bottom center</div>
</GradientBorder>Static gradient border (no animation)
<GradientBorder colors={['#ff006e', '#8338ec']} animate={false}>
<div>Static gradient border</div>
</GradientBorder>Custom colors and thickness
<GradientBorder
colors={['#9b5de5', '#f15bb5']}
strokeWidth={4}
borderRadius={24}
>
<div>Purple to pink gradient</div>
</GradientBorder>Hover trigger
<GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff']}
trigger="hover"
duration={800}
>
<div>Border appears on hover</div>
</GradientBorder>Focus trigger (great for inputs)
<GradientBorder
colors={['#4facfe', '#00f2fe', '#43e97b']}
trigger="focus"
duration={600}
>
<input type="text" placeholder="Focus me..." />
</GradientBorder>Click toggle
<GradientBorder
colors={['#ff006e', '#8338ec']}
trigger="click"
>
<div>Click to toggle border</div>
</GradientBorder>Continuous loop animation
<GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff', '#00f5d4']}
animationMode="loop"
duration={3000}
>
<div>Gradient continuously animates around</div>
</GradientBorder>Split animation (draw from both directions)
<GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff', '#00f5d4']}
variant="split"
duration={2000}
>
<div>Gradient draws from both directions and meets in the middle</div>
</GradientBorder>Ants marching (dashed border)
<GradientBorder
colors={['#ff006e', '#8338ec', '#3a86ff']}
ants
animationMode="loop"
>
<div>Marching ants border effect</div>
</GradientBorder>Outer border
<GradientBorder
colors={['#ff006e', '#8338ec']}
borderPosition="outer"
strokeWidth={4}
>
<div>Border drawn outside the element</div>
</GradientBorder>Border with offset
<GradientBorder
colors={['#ff006e', '#8338ec']}
borderOffset={8}
>
<div>Border offset 8px outward from inner edge</div>
</GradientBorder>Manual control
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>
</>
);
}Replay animation
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>
</>
);
}How It Works
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.
Browser Support
This component uses:
ResizeObserverfor responsive sizingIntersectionObserverfor lazy loadingrequestAnimationFramefor smooth animations
These APIs are supported in all modern browsers.
License
MIT
