npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-gradient-borders

v1.0.0

Published

Animated gradient borders for React components with SVG-based path-following gradients

Readme

react-gradient-borders

Animated gradient borders for React components using SVG-based path-following gradients.

Installation

npm install react-gradient-borders

Usage

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 the active prop

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:

  • ResizeObserver for responsive sizing
  • IntersectionObserver for lazy loading
  • requestAnimationFrame for smooth animations

These APIs are supported in all modern browsers.

License

MIT