Account

Backgrounds

Free

Animated Gradient

So a section feels lit rather than painted. Pure CSS, any number of colours.

Install

No key needed.

Terminal
npx @galactrex/ui add animated-gradient

Usage

Example
import { AnimatedGradient } from "@/components/galactrex/animated-gradient";

<section className="relative overflow-hidden">
  <AnimatedGradient />
  <h1 className="relative">Welcome</h1>
</section>

Source

Installs to components/galactrex/animated-gradient.tsx, with the shared motion primitives beside it.

components/galactrex/animated-gradient.tsx
"use client";
import { useRef } from "react";
import { cx } from "@/components/galactrex/motion/cx";
import { useReducedMotion } from "@/components/galactrex/motion/use-reduced-motion";
import { useVisible } from "@/components/galactrex/motion/use-visible";

export type AnimatedGradientProps = {
  /** two or more CSS colours; defaults to the background lit by the theme spectrum's blue and violet */
  colors?: readonly string[];
  /** direction in degrees */
  angle?: number;
  /** seconds for one pass; the gradient flows there and back */
  duration?: number;
  /** strength over the parent's own background, 0 to 1 */
  opacity?: number;
  className?: string;
};

const QUIET = ["var(--gxui-bg)", "var(--gxui-spectrum-2)", "var(--gxui-spectrum-3)", "var(--gxui-bg)"] as const;

/** A linear gradient that drifts slowly across its colours, so a section feels lit rather than painted. Pure CSS.
    Place it inside a relative parent, behind content; keep text contrast in mind when you pass bright colours.
    Holds still offscreen and with reduced motion. */
export function AnimatedGradient({ colors = QUIET, angle = 120, duration = 14, opacity = 0.5, className }: AnimatedGradientProps) {
  const ref = useRef<HTMLDivElement>(null);
  const reduced = useReducedMotion();
  const visible = useVisible(ref);
  const stops = colors.length > 1 ? colors : QUIET;
  return (
    <div
      ref={ref}
      aria-hidden
      className={cx("pointer-events-none absolute inset-0", className)}
      style={{
        opacity: Math.min(1, Math.max(0, opacity)),
        backgroundImage: `linear-gradient(${angle}deg, ${[...stops, stops[0]].join(", ")})`,
        backgroundSize: "300% 300%",
        backgroundPosition: "0% 50%",
        animation: !reduced && visible && duration > 0 ? `gxui-gradient-flow ${duration}s ease-in-out infinite alternate` : undefined,
      }}
    />
  );
}

Props

PropTypeDefaultDescription
colorsstring[]—Two or more CSS colours; defaults to quiet theme surfaces.
anglenumber120Direction in degrees.
durationnumber14Seconds for one pass, there and back.
opacitynumber0.5Strength, 0 to 1.
classNamestring—Extra classes for the outer element.

Variants

  • Quiet. Theme surfaces.
  • Brand. Pass `colors` for a brand wash.

Accessibility

  • Decorative only and aria-hidden; never takes pointer events.
  • Check text contrast when passing bright colours.

Motion and reduced motion

  • One CSS background-position animation.
  • Still offscreen.
  • Reduced motion: a still gradient.