Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Terrain Background for React

A shaded relief map: hills climb from sage valleys to snowy peaks in lit, layered levels edged with contour lines, panning slowly. For React with Base UI, when an outdoor, mapping or travel page needs a calm, tactile cartographic backdrop.

Framework

A shaded relief map behind your content: the ground climbs in fifteen levels from sage valleys through olive and sand to warm stone and snowy peaks, each level lit from the north-west, so it catches a thin line of light on one side and casts a soft shadow on the level below on the other. A fine contour line edges every level, and every fifth one is heavier, like the index contours on a survey map. On a light page it's a paper map; on a dark one, a cool slate relief at night. The map is traced from a seeded noise field when the component renders, so the same seed always draws the same hills, on the server and in the browser; the light and shadow are CSS drop shadows, drawn once, and the map pans slowly back and forth with one CSS animation, so nothing is recomputed or repainted while it moves.

Use it for outdoor, travel, mapping, geo and climate pages, behind a hero or a section. For contour lines alone, use Topography; for flat seeded cells instead of landforms, Voronoi; for soft color without any shapes, Mesh Gradient.

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 { Terrain } from "@/components/ui/terrain";
<Terrain className="flex min-h-[480px] items-center justify-center">
  <h1 className="text-5xl font-semibold">Map the world</h1>
</Terrain>

Terrain is a container: give it a size, put your content inside, and the map sits behind it. The palette is quiet in both themes, so copy can sit on the map directly. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10".

Demos

Paper relief

lines={false} drops the contour lines, so the levels show as stacked, lit terraces, like a relief cut from layers of paper. scale={1.6} draws smaller hills, more of them in the card, and seed={9} draws another map.

Preview width

Monochrome

colors takes up to five CSS colors, valleys first; the levels between are mixed from them. Here five tints of the theme's text over its background give a gray relief that follows light and dark mode, and --terrain-line, set in className, softens the contour lines to the text color at 30%.

Preview width

Accessibility

The map is decoration: it's hidden from assistive tech and never takes the pointer. With reduced motion it stays where it is, the whole relief still drawn. Nothing flashes.

Put copy over it in your foreground color (text-foreground). The default palettes keep it readable everywhere: the light map stays pale, its shadows included, and the night relief stays dark, its lit peaks included. With your own colors, check your copy against the darkest and the lightest of them.

FAQ

How is this different from Topography?

Topography draws only the contour lines, on your page's background. Terrain fills the ground between them with color by height and lights every level, so the hills read in relief. Both trace their shapes from the same kind of seeded noise when they render.

Can I recolor it?

Yes. colors takes up to five CSS colors, from the valleys to the peaks, and the fifteen levels are mixed between them; the colors you pass apply in both themes. You can also set --terrain-color-1 to --terrain-color-5, --terrain-line, --terrain-highlight and --terrain-shadow in your CSS.

What does lines={false} do?

It drops the contour lines. The levels keep their light and shadow, so the map reads as stacked terraces, like a paper relief, a little calmer behind text.

How do I get a different map?

Change seed: every number draws other hills, and the same number always draws the same ones. scale sets their size: 2 draws twice as many, each half as wide.

Does the map morph like a live satellite feed?

No, it pans. Morphing the hills means tracing every level again each frame; panning a map drawn once costs nothing while it moves. speed scales the pan, and speed={0} holds it still.

Is it heavy?

Not while it runs: the levels and their shadows are drawn once, then the browser only slides the finished map, with no script and no repaint. Drawing it the first time, after a resize or a theme switch, takes the browser a moment longer than a flat background.

What happens with reduced motion?

The map stays where it is: the same relief, without the pan.

API Reference

Terrain

<div> data-slot="terrain"

PropType
colors?string[]

Up to five CSS colours for the ground, from the valleys to the peaks; the levels between are mixed from them. By default a paper map (sage, olive, sand, stone, snow) on a light page and a cool night relief on a dark one.

lines?boolean

Whether a contour line edges every level, every fifth one heavier. @default true.

Default
true
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 pans, 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
--terrain-color-1string

The valleys' colour; up to --terrain-color-5, the peaks'.

--terrain-highlightstring

The light along each level's north-west edge.

--terrain-linestring

The contour lines' colour (a brown ink, pale on a dark page).

--terrain-shadowstring

The shadow each level casts to the south-east.

--terrain-speedstring

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

All 100 backgrounds