Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Topography Background for React

A topographic map behind your content: contour rings around hills and hollows that draw in once, then drift. For React with Base UI, when an outdoor, mapping or data page needs a quiet cartographic backdrop.

Framework

A topographic map behind your content: thin contour lines circle hills and hollows, every fifth one heavier, like the index contours on a survey map. The map is traced from a seeded noise field when the component renders, so the same seed always draws the same map, on the server and in the browser. The lines draw in once, level by level, then the whole map pans and zooms slowly with one CSS animation; nothing is recomputed or repainted while it moves.

Use it for outdoor, travel, mapping and data pages, where a line drawing fits better than color. For filled, colored altitude bands, use Terrain; for a wireframe surface rising and falling as waves cross it, Wave Grid; for a plain structural backdrop, Grid Pattern.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { Topography } from "@/components/ui/topography";
<Topography className="flex min-h-[480px] items-center justify-center">
  <h1 className="text-5xl font-semibold">Find your next trail</h1>
</Topography>

Topography is a container: give it a size, put your content inside, and the map sits behind it. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10".

Demos

In a card

The map fills any box. Here seed={4} draws a different map, count={8} keeps it sparse, and fade="none" runs the lines to the card's edges.

Preview width

Color

lineColor takes any CSS color, here the theme's primary at 45%. count={18} gives a denser map, and the --topography-stroke variable, set to 1.25 in the class, a bolder line.

Preview width

Accessibility

The map is decoration: it's hidden from assistive tech and never takes the pointer. With reduced motion the lines appear complete and the map stays still. Nothing flashes.

The lines are 18% of your text color by default, so copy on top in text-foreground keeps its full contrast; the radial fade also keeps the middle of the box calm. A strong lineColor behind small text deserves a lower opacity.

FAQ

How are the contour lines made?

A small noise function gives a height at each point of a 48 × 30 grid. For each level, the component finds where the height crosses it in every cell (marching squares), joins those crossings into rings and smooths them into one SVG path per level. That happens once, when it renders.

Does the map change on every load?

No. One seed draws one map, the same on the server and in the browser, so the page never flickers on hydration. Pass another seed for another map, and scale={2} for twice as many, smaller hills.

What moves?

First each level's line draws itself in, 80 ms after the level below. Then the whole map pans and zooms slowly, back and forth, with one CSS transform on a wrapper. speed scales that drift, and speed={0} holds the map still.

How do I change the density and the color?

count sets the number of levels, from 3 to 24; every fifth line is heavier. lineColor takes any CSS color. The width is the --topography-stroke variable, in pixels (className="[--topography-stroke:1.5]"), and stays the same in a small card and a full-width hero.

Can I turn off the fade at the edges?

Yes. fade is radial by default; top and bottom fade only that edge, and none runs the lines to every edge.

What happens with reduced motion?

The lines appear complete, with no draw-in, and the map stays where it is.

API Reference

Topography

<div> data-slot="topography"

PropType
count?number

How many contour levels, from 3 to 24. Every fifth is drawn heavier, like a map's index contours.

Default
12
fade?"none" | "radial" | "top" | "bottom"

Where the lines fade out: toward every edge, toward the top, toward the bottom, or nowhere.

Type
"none" | "radial" | "top" | "bottom"
Default
"radial"
lineColor?string

The lines' colour, any CSS colour.

Default
18% of `var(--foreground)`
scale?number

The size of the hills: 2 draws twice as many, each half as wide. @default 1.

Default
1
seed?number

Which map to draw. The same seed always draws the same map, on the server and in the browser.

Default
1
speed?number

How fast the map drifts, as a multiplier: 2 is twice as fast, 0 holds it still.

Default
1
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CSS variableType
--topography-colorstring

The lines' colour (18% of --foreground).

--topography-speedstring

How fast the map drifts, a multiplier (1).

--topography-strokestring

The lines' width in pixels (1); index lines are 1.75 times as wide.

All 100 backgrounds