Topography Background

Living contour lines, like a map of a terrain that slowly breathes. A hill rises under the cursor and a click sends a wave across.

"use client"

import { TopographyBackground } from "@/components/animate-ui/backgrounds/topography"

const COLORS = {
  text: "",
  blue: "#3b9eff",
  violet: "#a78bfa",
  emerald: "#34d399",
  amber: "#fbbf24",
  rose: "#fb7185",
}

export default function TopographyBackgroundDemo({
  lineColor = "",
  levels = 16,
  speed = 1,
  scale = 1,
  peak = 1,
  interactive = true,
}: {
  lineColor?: string
  levels?: number
  speed?: number
  scale?: number
  peak?: number
  interactive?: boolean | string
}) {
  return (
    <TopographyBackground
      className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,#fafafa_0%,#f0f0f0_100%)] text-neutral-500 dark:bg-[radial-gradient(ellipse_at_center,#171717_0%,#000_100%)] dark:text-neutral-400"
      lineColor={lineColor || undefined}
      levels={Number(levels)}
      speed={Number(speed)}
      scale={Number(scale)}
      peak={Number(peak)}
      interactive={interactive === true || interactive === "true"}
    />
  )
}

Installation

npx shadcn@latest add @animate-ui/backgrounds-topography
pnpm dlx shadcn@latest add @animate-ui/backgrounds-topography
yarn dlx shadcn@latest add @animate-ui/backgrounds-topography
bun x shadcn@latest add @animate-ui/backgrounds-topography

Usage

import { TopographyBackground } from '@/components/animate-ui/backgrounds/topography';

export function Hero() {
  return (
    <section className="relative h-[480px] overflow-hidden">
      <TopographyBackground className="absolute inset-0 text-neutral-500" />
    </section>
  );
}

Animation

  • The terrain is a field of gradient noise drawn as contour lines, like a topographic map: every fifth line is an index contour, thicker and brighter. The noise drifts slowly through time (speed), so the relief keeps reshaping itself.
  • On mount, the relief rises from flat ground in 1.8s on an ease-out: the lines bloom out from the middle level.
  • Under the cursor, a peak rises on a spring and follows it (transition), its rings tightening towards the summit (peak). Leaving the container lets it sink back.
  • A click (or a tap) drops a wave: a crest and a trough travel out from the point in 2.6s, bunching the lines as they pass, and fade away.
  • The lines take the container's text color, or lineColor. They're drawn with WebGL, pixel by pixel on the GPU (at most twice the device pixel ratio): no grid, so they glide without stepping and redraw on every frame, even at 120Hz and more. Where WebGL is missing, a canvas draws them as smooth curves instead.
  • The loop pauses off screen and while the tab is hidden.
  • Under reduced motion, the terrain is a still map: no drift, no peak, no wave.

API Reference

TopographyBackground

PropTypeDefault
lineColor?
string-
levels?
number16
speed?
number1
scale?
number1
peak?
number1
interactive?
booleantrue
transition?
SpringOptions{ stiffness: 120, damping: 20 }
...props?
React.ComponentProps<'div'>-

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/18/2026

On this page