Skip to main content

Overview

The BackgroundGradient component wraps content with an animated, multi-color radial gradient border effect. It features smooth background position animations and interactive hover states, creating a premium, modern visual effect.

Visual Effect

The component creates:
  • Two layered animated gradient effects (blurred and sharp)
  • Four radial gradients positioned at corners: cyan, purple, yellow, and blue
  • Smooth background position animation that loops infinitely
  • Opacity transition on hover (60% → 100%)
  • Blur effect on the bottom gradient layer

Source Location

/workspace/source/src/app/components/ui/background-gradient.tsx

Props

children
React.ReactNode
Content to be wrapped with the gradient effect
className
string
Additional classes for the inner content wrapper (z-index 10)
containerClassName
string
Additional classes for the outer container element
animate
boolean
default:true
Whether to enable the background position animation. Set to false for a static gradient.

Type Definition

From /workspace/source/src/app/components/ui/background-gradient.tsx:5-14:
export const BackgroundGradient = ({
  children,
  className,
  containerClassName,
  animate = true,
}: {
  children?: React.ReactNode;
  className?: string;
  containerClassName?: string;
  animate?: boolean;
})

Animation Details

The component uses Framer Motion for smooth animations.

Motion Variants

From /workspace/source/src/app/components/ui/background-gradient.tsx:16-23:
const variants = {
  initial: {
    backgroundPosition: "0 50%",
  },
  animate: {
    backgroundPosition: ["0, 50%", "100% 50%", "0 50%"],
  },
};

Transition Configuration

duration
number
default:5
Animation duration in seconds
repeat
number
default:null
Number of times to repeat the animation
repeatType
string
default:"reverse"
How the animation repeats (“reverse” creates a back-and-forth effect)
The animation only applies when animate={true}. When disabled, all motion props are set to undefined.

Gradient Color Scheme

The gradient uses four radial gradients positioned at each corner:
background: radial-gradient(
  circle farthest-side at 0 100%,    /* Bottom-left */
  #00ccb1,                           /* Cyan */
  transparent
),
radial-gradient(
  circle farthest-side at 100% 0,    /* Top-right */
  #7b61ff,                           /* Purple */
  transparent
),
radial-gradient(
  circle farthest-side at 100% 100%, /* Bottom-right */
  #ffc414,                           /* Yellow */
  transparent
),
radial-gradient(
  circle farthest-side at 0 0,       /* Top-left */
  #1ca0fb,                           /* Blue */
  #141316                            /* Dark base */
)

Usage Examples

Profile Image Wrapper

From /workspace/source/src/app/components/sections/ProfileCard.tsx:14-23:
import { BackgroundGradient } from "../ui/background-gradient";
import Image from "next/image";

export default function ProfileCard() {
  return (
    <div className="relative col-span-2 row-span-6 bg-spotify-light-dark rounded-xl p-4">
      <BackgroundGradient containerClassName="rounded-[40px] place-self-center">
        <Image
          src="/luan_real.jpg"
          alt="Luan Nguyen"
          width={400}
          height={400}
          className="rounded-[25px] object-cover"
          priority
        />
      </BackgroundGradient>
    </div>
  );
}

Card with Content

import { BackgroundGradient } from "@/components/ui/background-gradient";

export default function FeatureCard() {
  return (
    <BackgroundGradient className="rounded-[22px] p-6 bg-zinc-900">
      <h3 className="text-xl font-bold mb-2">Premium Feature</h3>
      <p className="text-gray-400">
        This card has an animated gradient border effect.
      </p>
    </BackgroundGradient>
  );
}

Static Gradient (No Animation)

<BackgroundGradient animate={false} className="p-4">
  <p>Content with static gradient border</p>
</BackgroundGradient>
Use animate={false} for static elements or to reduce motion for accessibility preferences.

Layer Structure

The component creates three layers:
  1. Outer Container (relative p-[4px] group)
    • 4px padding creates the border effect
    • group enables hover state targeting
  2. Gradient Layers (both absolute inset-0 z-[1])
    • Bottom layer: Blurred gradient with opacity transition
    • Top layer: Sharp gradient
    • Both animated with same motion variants
  3. Content Layer (relative z-10)
    • Sits above gradients
    • Contains your custom content

Styling Classes

Container

"relative p-[4px] group"

Blurred Gradient Layer

"absolute inset-0 rounded-3xl z-[1] opacity-60 group-hover:opacity-100 blur-xl transition duration-500 will-change-transform"

Sharp Gradient Layer

"absolute inset-0 rounded-3xl z-[1] will-change-transform"

Content Wrapper

"relative z-10"
The will-change-transform property optimizes animation performance by hinting to the browser about upcoming transforms.

Performance Considerations

  • GPU Acceleration: Uses will-change-transform for smooth animations
  • Conditional Animation: Disable with animate={false} for static use cases
  • Background Size: Set to 400% 400% when animated to allow smooth position transitions

Dependencies

  • framer-motion - For animation capabilities
  • @/lib/utils - Provides cn() utility for class merging
  • React
  • Tailwind CSS

Accessibility

The component respects user motion preferences:
// Disable animation for users who prefer reduced motion
<BackgroundGradient 
  animate={!window.matchMedia('(prefers-reduced-motion: reduce)').matches}
>
  {children}
</BackgroundGradient>

Customization Tips

  1. Border Width: Adjust the p-[4px] padding in containerClassName prop
  2. Corner Radius: Modify rounded-3xl classes
  3. Colors: The gradient colors are hardcoded—edit the component source to customize
  4. Animation Speed: Change the duration: 5 value in the transition config
  5. Hover Behavior: The blur layer transitions from 60% to 100% opacity on hover

Build docs developers (and LLMs) love