# AmbientBackground (/docs/ambient-background)





You're looking at it right now — this docs site renders `AmbientBackground` once, in its root layout, and every page you navigate to (including this one) is the live example.

```tsx
import { AmbientBackground } from "@42-central/ui-react/ambient-background";

// app/layout.tsx
<body>
  <AmbientBackground />
  {children}
</body>;
```

Render it once, as the first child of your root layout. It's `position: fixed`, so a single instance covers the whole viewport regardless of scroll position or page height — later content naturally paints over it as long as it's mounted first. It's purely decorative: `aria-hidden`, `pointer-events-none`, and hidden under `forced-colors` (Windows High Contrast Mode), since a background tint has no place overriding a user's forced palette.

The glow and noise are CSS custom properties (`--ambient-glow` / `--ambient-noise`, defined once in `theme.css`, brand-tinted and theme-aware via `data-theme`) rather than hardcoded in the component — override either on `:root` in your own stylesheet to reskin it without forking the component.

Glow and noise render as two independent `position: fixed` elements rather than one wrapper containing two children — nesting the noise layer's blend mode inside a `fixed` wrapper would trap it inside that wrapper's own isolated stacking context, unable to blend against the real page content underneath. The examples below constrain each layer to a bounded box via `classNames` (overriding the default `fixed inset-0 -z-10` on each) purely so they fit inside the preview frame — in real use you pass no props at all.

## Both layers (default) [#both-layers-default]

<Preview align="block" code="`<AmbientBackground />`">
  <div className="relative h-64 overflow-hidden rounded-lg border border-brand-900/20 bg-brand-50 dark:border-white/15 dark:bg-brand-950">
    <AmbientBackground classNames="{ glow: &#x22;absolute inset-0 z-0&#x22;, noise: &#x22;absolute inset-0 z-0&#x22; }" />

    <div className="relative flex h-full items-center justify-center text-sm text-gray-light-500 dark:text-gray-dark-400">
      Page content
    </div>
  </div>
</Preview>

## Glow only [#glow-only]

Turn off the noise layer with `noise={false}` for just the radial tint.

<Preview align="block" code="`<AmbientBackground noise={false} />`">
  <div className="relative h-64 overflow-hidden rounded-lg border border-brand-900/20 bg-brand-50 dark:border-white/15 dark:bg-brand-950">
    <AmbientBackground noise="false" classNames="{ glow: &#x22;absolute inset-0 z-0&#x22; }" />
  </div>
</Preview>

## Noise only [#noise-only]

Turn off the glow with `glow={false}` for just the grain texture — useful over a background you're already tinting yourself.

<Preview align="block" code="`<AmbientBackground glow={false} />`">
  <div className="relative h-64 overflow-hidden rounded-lg border border-brand-900/20 bg-brand-50 dark:border-white/15 dark:bg-brand-950">
    <AmbientBackground glow="false" classNames="{ noise: &#x22;absolute inset-0 z-0&#x22; }" />
  </div>
</Preview>

## API [#api]

<TypeTable
  type="{
  glow: {
    type: 'boolean',
    default: 'true',
    description: 'Render the radial glow layer.',
  },
  noise: {
    type: 'boolean',
    default: 'true',
    description: 'Render the film-grain noise layer.',
  },
  classNames: {
    type: '{ glow?: string; noise?: string }',
    description: 'Per-layer class overrides. There is no shared wrapper element to target — see why in the note above.',
  },
}"
/>

## Accessibility [#accessibility]

`AmbientBackground` is purely decorative:

* `aria-hidden="true"` — assistive tech skips it entirely.
* `pointer-events-none` — it never intercepts clicks or taps meant for real content underneath.
* `forced-colors:hidden` — it disappears under Windows High Contrast Mode, since a decorative tint has no place overriding a user's forced palette there.
