Backgrounds

Gradient Mesh

A mesh gradient background — five soft radial-gradient color points drift slowly via transform, weaving into a flowing mesh.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add gradient-mesh.en

New project or installation trouble? Start here →

Gradient Mesh is a React animated mesh gradient background built with Tailwind CSS and Motion. Five blurred radial-gradient points drift slowly on different cycles to produce a gradient that keeps flowing, and your foreground content goes straight into children.

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

1
Active edited usageDefault props
<GradientMesh/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

When to use

  • The hero background of a SaaS or app landing page, behind the headline and call to action.
  • The visual half of a sign-up or login page, or the full background of a waitlist page.
  • Large card backgrounds in pricing or feature highlight sections, tuned to brand colors.
  • Banner sections on event or product launch pages.
  • Not a good fit: for larger flowing color fields with grain or cursor following, see Aurora Background.

Installation

npx webberui@latest add https://webberui.com/r/gradient-mesh.en.json

Or, once registries are configured in components.json, install it as @webberui/gradient-mesh.

Usage

Put your foreground content in children, and write the layout (centering, height) on className:

import { GradientMesh } from "@/components/ui/gradient-mesh";

<GradientMesh className="flex min-h-[400px] items-center justify-center">
  <h1 className="text-4xl font-bold">Hero heading</h1>
</GradientMesh>

Custom colors and drift speed:

<GradientMesh
  colors={["#f0abfc", "#c4b5fd", "#7dd3fc", "#6ee7b7"]}
  speed={1.5}
  className="flex h-[320px] items-center justify-center rounded-2xl"
>
  <p className="text-lg">A faster, pinker mesh</p>
</GradientMesh>

Examples

Hero section with a call to action

className sets the height and layout; the headline and button go in children and sit above the gradient.

import { GradientMesh } from "@/components/ui/gradient-mesh";

export function Hero() {
  return (
    <GradientMesh className="flex min-h-[520px] flex-col items-center justify-center gap-6 px-6 text-center">
      <h1 className="max-w-2xl text-5xl font-semibold tracking-tight">
        Keep your team's docs in one place
      </h1>
      <a href="/signup" className="rounded-full bg-neutral-900 px-5 py-2.5 text-sm font-medium text-white dark:bg-white dark:text-neutral-900">
        Try it without signing up
      </a>
    </GradientMesh>
  );
}

Two-color brand palette

colors maps to the five points in order and cycles when there are fewer colors, so passing two colors makes them alternate.

<GradientMesh
  colors={["#2563eb", "#14b8a6"]}
  className="h-[360px] rounded-3xl"
/>

Card background at a slower speed

speed is a drift multiplier, so values below 1 are slower; add rounded-* and padding to use it as a card background.

<GradientMesh speed={0.5} className="rounded-2xl p-8">
  <h3 className="text-lg font-semibold">Team plan</h3>
  <p className="mt-2 text-sm text-neutral-600 dark:text-neutral-300">
    Shared workspaces, permissions, and audit logs.
  </p>
</GradientMesh>

Props

PropTypeDefaultDescription
colorsstring[]Soft multicolor paletteMesh point colors, mapped in order to each point and cycled when there are not enough
speednumber1Drift speed multiplier — higher flows faster (the period is divided by this value)
childrenReact.ReactNode—Foreground content, layered above the mesh
classNamestring—Appended to the outermost container's className

How it works

  • Performance: transform only. Every point drifts via x / y, never touching top / left, so neither layout nor paint is triggered; will-change is managed automatically by Motion during the animation, so you never set it by hand
  • Each point's x and y axes use different periods (12s–22s) paired with repeat: Infinity + repeatType: "mirror". With the two axes offset from each other, each point traces an arc, and the five points never sync up — the result reads as a naturally flowing mesh
  • The points are blur-3xl radial-gradient circles — the blur is composited once by the GPU and then translated by transform, so its cost is fixed and does not accumulate over the animation
  • The whole background layer is pointer-events-none and sits at -z-10 beneath the content (the container has isolate to create its own stacking context), so foreground interaction is completely unaffected
  • speed is guarded: non-positive values fall back to 1, so the period never becomes Infinity or runs in reverse
  • The base color is neutral-50 / neutral-950, so the mesh stays crisp and easy on the eyes in both light and dark mode

Accessibility

  • The background layer carries aria-hidden — it is decorative only, so it does not interfere with assistive technology
  • When the user has "reduce motion" enabled at the system level, all points stop drifting and render as static gradients, with no change to the DOM structure

FAQ

Does it work with the Next.js App Router?

Yes. The source already has "use client", so import it from a Server Component page directly. The first render matches the server output and only switches to the static version after mount when reduced motion is on, so there is no hydration mismatch.

Will it slow the page down?

The points only animate transform (x and y), so they never trigger layout; the animation is driven by Motion, with no canvas or per-pixel work.

How do I change the colors, speed, and base color?

Pass an array of CSS colors to colors and adjust the drift multiplier with speed (non-positive values fall back to 1). The base color is bg-neutral-50 dark:bg-neutral-950 on the container; override it by passing another bg-* in className.

Does it block clicks on the foreground content?

No. The gradient layer is pointer-events-none and sits below the content at -z-10, and the container uses isolate to create its own stacking context.

What happens when the user prefers reduced motion?

All points stop drifting and render as a static gradient, with the same DOM structure.