# Texture Overlay

> CSS texture overlay for React and shadcn/ui with dots, grid, crosshatch, halftone, and paper grain patterns at any opacity.

Source: https://www.cult-ui.com/docs/components/texture-overlay

## Example

```tsx title="texture-overlay-demo.tsx"
"use client"

import { TextureOverlay } from "@/components/ui/texture-overlay"

export default function TextureOverlayDemo() {
  return (
    <div className="flex justify-center rounded-md px-4 py-6 md:px-0 dark:bg-stone-950">
      <div className="w-full max-w-6xl">
        <div className="mb-12 space-y-4 text-center">
          <h2 className="text-foreground text-3xl font-bold tracking-tight">
            Texture Overlay Showcase
          </h2>
          <p className="text-muted-foreground mx-auto max-w-2xl text-lg">
            Explore different texture patterns using CSS gradients for adding
            visual texture to backgrounds and surfaces.
          </p>
        </div>

        <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
          {[
            { type: "dots" as const, name: "Dots Pattern" },
            { type: "grid" as const, name: "Grid Pattern" },
            { type: "noise" as const, name: "Noise Pattern" },
            { type: "crosshatch" as const, name: "Crosshatch Pattern" },
            { type: "diagonal" as const, name: "Diagonal Pattern" },
            { type: "scatteredDots" as const, name: "Scattered Dots" },
            { type: "halftone" as const, name: "Halftone Pattern" },
            { type: "triangular" as const, name: "Triangular Pattern" },
            { type: "chevron" as const, name: "Chevron Pattern" },
            { type: "paperGrain" as const, name: "Paper Grain" },
            { type: "horizontalLines" as const, name: "Horizontal Lines" },
            { type: "verticalLines" as const, name: "Vertical Lines" },
          ].map((texture) => (
            <div
              key={texture.type}
              className="bg-card relative h-48 overflow-hidden rounded-lg border shadow-[0px_1px_0px_0px_hsla(0,_0%,_0%,_0.02)_inset,_0px_0px_0px_1px_hsla(0,_0%,_0%,_0.02)_inset,_0px_0px_0px_1px_rgba(255,_255,_255,_0.25)]"
            >
              <TextureOverlay texture={texture.type} />
              <div className="relative z-10 flex h-full items-end p-6">
                <div className="bg-background/80 rounded-md border px-3 py-2 backdrop-blur-sm">
                  <h3 className="text-foreground font-medium">
                    {texture.name}
                  </h3>
                  <p className="text-muted-foreground text-sm">
                    {texture.type} texture
                  </p>
                </div>
              </div>
            </div>
          ))}
        </div>

        <div className="mt-12 space-y-8">
          <div className="text-center">
            <h3 className="text-foreground mb-4 text-2xl font-bold tracking-tight">
              Opacity Variations
            </h3>
            <p className="text-muted-foreground mb-8">
              See how different opacity values affect the texture appearance
            </p>
          </div>

          <div className="grid grid-cols-1 gap-6 md:grid-cols-3">
            {[0.3, 0.6, 1.0].map((opacity) => (
              <div
                key={opacity}
                className="bg-card relative h-32 overflow-hidden rounded-lg border shadow-[0px_1px_0px_0px_hsla(0,_0%,_0%,_0.02)_inset,_0px_0px_0px_1px_hsla(0,_0%,_0%,_0.02)_inset,_0px_0px_0px_1px_rgba(255,_255,_255,_0.25)]"
              >
                <TextureOverlay texture="dots" opacity={opacity} />
                <div className="relative z-10 flex h-full items-end p-4">
                  <div className="bg-background/80 rounded-md border px-3 py-2 backdrop-blur-sm">
                    <h4 className="text-foreground font-medium">
                      Dots Pattern
                    </h4>
                    <p className="text-muted-foreground text-sm">
                      Opacity: {opacity}
                    </p>
                  </div>
                </div>
              </div>
            ))}
          </div>

          <div className="text-center">
            <h3 className="text-foreground mb-4 text-2xl font-bold tracking-tight">
              Custom Styling
            </h3>
            <p className="text-muted-foreground mb-8">
              Combine with custom classes for unique effects
            </p>
          </div>

          <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
            <div className="relative h-32 overflow-hidden rounded-lg bg-gradient-to-br from-blue-500 to-purple-600">
              <TextureOverlay texture="grid" className="mix-blend-overlay" />
              <div className="relative z-10 flex h-full items-center justify-center p-4">
                <div className="bg-background/80 rounded-md border px-3 py-2 backdrop-blur-sm">
                  <h4 className="text-foreground font-medium">
                    Grid with Blend Mode
                  </h4>
                  <p className="text-muted-foreground text-sm">
                    mix-blend-overlay
                  </p>
                </div>
              </div>
            </div>

            <div className="relative h-32 overflow-hidden rounded-lg bg-gradient-to-br from-green-500 to-teal-600">
              <TextureOverlay texture="noise" className="opacity-50" />
              <div className="relative z-10 flex h-full items-center justify-center p-4">
                <div className="bg-background/80 rounded-md border px-3 py-2 backdrop-blur-sm">
                  <h4 className="text-foreground font-medium">
                    Noise with Custom Opacity
                  </h4>
                  <p className="text-muted-foreground text-sm">
                    opacity-50 class
                  </p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}
```

Texture Overlay is a React component for shadcn/ui built on pure CSS gradients. Use it to add subtle texture to hero backgrounds, cards, and section dividers.

## Installation

### CLI

```bash
npx shadcn@latest add @cult-ui/texture-overlay
```

### Manual

**Copy and paste the following code into your project.**

```tsx title="texture-overlay.tsx"
import { cn } from "@/lib/utils"

export type TextureType =
  | "dots"
  | "grid"
  | "noise"
  | "crosshatch"
  | "diagonal"
  | "scatteredDots"
  | "halftone"
  | "triangular"
  | "chevron"
  | "paperGrain"
  | "horizontalLines"
  | "verticalLines"
  | "none"

interface TextureOverlayProps {
  texture: TextureType
  opacity?: number
  className?: string
}

const texturePatterns: Record<TextureType, string> = {
  dots: "bg-[radial-gradient(circle_at_1px_1px,rgba(0,0,0,0.4)_1px,transparent_0)] bg-[length:8px_8px]",
  grid: "bg-[linear-gradient(rgba(0,0,0,0.3)_1px,transparent_1px),linear-gradient(90deg,rgba(0,0,0,0.3)_1px,transparent_1px)] bg-[length:12px_12px]",
  noise:
    "bg-[radial-gradient(circle_at_2px_2px,rgba(0,0,0,0.25)_1px,transparent_0)] bg-[length:6px_6px]",
  crosshatch:
    "bg-[repeating-linear-gradient(45deg,transparent,transparent_2px,rgba(0,0,0,0.3)_2px,rgba(0,0,0,0.3)_4px),repeating-linear-gradient(-45deg,transparent,transparent_2px,rgba(0,0,0,0.3)_2px,rgba(0,0,0,0.3)_4px)]",
  diagonal:
    "bg-[repeating-linear-gradient(-45deg,rgba(0,0,0,0.2),rgba(0,0,0,0.2)_1px,transparent_1px,transparent_6px)]",
  scatteredDots:
    "bg-[radial-gradient(circle_at_3px_7px,rgba(0,0,0,0.3)_1px,transparent_0),radial-gradient(circle_at_11px_2px,rgba(0,0,0,0.3)_1px,transparent_0),radial-gradient(circle_at_7px_12px,rgba(0,0,0,0.3)_1px,transparent_0)] bg-[length:16px_16px]",
  halftone:
    "bg-[radial-gradient(circle,rgba(0,0,0,0.4)_25%,transparent_25%)] bg-[length:10px_10px] bg-[position:0_0,5px_5px]",
  triangular:
    "bg-[conic-gradient(from_0deg_at_50%_50%,rgba(0,0,0,0.3)_0deg_120deg,transparent_120deg_240deg,rgba(0,0,0,0.3)_240deg_360deg)] bg-[length:8px_8px] bg-[position:0_0,4px_4px]",
  chevron:
    "bg-[repeating-linear-gradient(45deg,rgba(0,0,0,0.2)_0px,rgba(0,0,0,0.2)_2px,transparent_2px,transparent_8px),repeating-linear-gradient(-45deg,rgba(0,0,0,0.2)_0px,rgba(0,0,0,0.2)_2px,transparent_2px,transparent_8px)]",
  paperGrain:
    "bg-[repeating-linear-gradient(0deg,rgba(0,0,0,0.1)_0px,transparent_1px,transparent_3px),repeating-linear-gradient(90deg,rgba(0,0,0,0.1)_0px,transparent_1px,transparent_4px),repeating-linear-gradient(45deg,rgba(0,0,0,0.05)_0px,transparent_1px,transparent_5px)]",
  horizontalLines:
    "bg-[repeating-linear-gradient(0deg,rgba(0,0,0,0.25)_0px,rgba(0,0,0,0.25)_1px,transparent_1px,transparent_4px)]",
  verticalLines:
    "bg-[repeating-linear-gradient(90deg,rgba(0,0,0,0.25)_0px,rgba(0,0,0,0.25)_1px,transparent_1px,transparent_4px)]",
  none: "",
}

const defaultOpacities: Record<TextureType, number> = {
  dots: 1,
  grid: 1,
  noise: 1,
  crosshatch: 1,
  diagonal: 1,

  scatteredDots: 1,
  halftone: 1,
  triangular: 1,
  chevron: 1,
  paperGrain: 1,
  horizontalLines: 1,
  verticalLines: 1,
  none: 0,
}

export function TextureOverlay({
  texture,
  opacity,
  className,
}: TextureOverlayProps) {
  if (texture === "none") return null

  const finalOpacity = opacity ?? defaultOpacities[texture]
  const pattern = texturePatterns[texture]

  return (
    <div
      className={cn("pointer-events-none absolute inset-0", pattern, className)}
      style={{ opacity: finalOpacity }}
    />
  )
}
```

**Update the import paths to match your project setup.**

## Usage

```tsx
import { TextureOverlay } from "@/components/ui/texture-overlay";
```

### Basic Usage

```tsx
<TextureOverlay texture="dots" />
<TextureOverlay texture="grid" opacity={0.5} />
<TextureOverlay texture="none" />
```

### With Custom Styling

```tsx
<div className="relative bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg p-8">
  <TextureOverlay texture="grid" className="mix-blend-overlay" />
  <div className="relative z-10">
    <h2>Content with texture overlay</h2>
  </div>
</div>
```

## API Reference

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `texture` | `TextureType` | - | The type of texture pattern to display |
| `opacity` | `number` | `defaultOpacities[texture]` | The opacity of the texture overlay (0-1) |
| `className` | `string` | - | Additional CSS classes to apply |

### TextureType

The `TextureType` union includes the following options:

- `"dots"` - Small circular dots pattern
- `"grid"` - Grid lines pattern
- `"noise"` - Random noise pattern
- `"crosshatch"` - Crosshatch pattern
- `"diagonal"` - Diagonal lines pattern
- `"radialDots"` - Radial dots from center
- `"scatteredDots"` - Scattered dots pattern
- `"halftone"` - Halftone dots pattern
- `"triangular"` - Triangular pattern
- `"chevron"` - Chevron pattern
- `"paperGrain"` - Paper grain texture
- `"horizontalLines"` - Horizontal lines
- `"verticalLines"` - Vertical lines
- `"none"` - No texture (component returns null)

## Examples

### Card with Texture Background

```tsx
<div className="relative bg-card rounded-lg p-6 shadow-lg">
  <TextureOverlay texture="paperGrain" opacity={0.3} />
  <div className="relative z-10">
    <h3 className="text-lg font-semibold">Card Title</h3>
    <p className="text-muted-foreground">Card content with subtle texture</p>
  </div>
</div>
```

### Hero Section with Texture

```tsx
<section className="relative min-h-screen bg-gradient-to-br from-slate-900 to-slate-800">
  <TextureOverlay texture="noise" opacity={0.4} />
  <div className="relative z-10 flex items-center justify-center">
    <div className="text-center">
      <h1 className="text-4xl font-bold text-white">Hero Title</h1>
      <p className="text-slate-300">Hero subtitle with texture background</p>
    </div>
  </div>
</section>
```

### Multiple Texture Layers

```tsx
<div className="relative bg-background rounded-lg p-8">
  <TextureOverlay texture="grid" opacity={0.2} />
  <TextureOverlay texture="dots" opacity={0.1} className="mix-blend-multiply" />
  <div className="relative z-10">
    <h2>Layered Textures</h2>
    <p>Combining multiple texture patterns</p>
  </div>
</div>
```

## Styling

The component uses CSS gradients to create texture patterns. You can customize the appearance by:

- Adjusting the `opacity` prop for transparency
- Adding custom `className` for additional styling
- Using CSS blend modes like `mix-blend-overlay` or `mix-blend-multiply`
- Combining multiple `TextureOverlay` components for layered effects

## Performance

The component is optimized for performance by:

- Using CSS gradients instead of images
- Minimal DOM footprint (single div element)
- No JavaScript animations or calculations
- Lightweight and fast rendering

## Accessibility

The component is designed to be accessible:

- Uses `pointer-events-none` to ensure it doesn't interfere with user interactions
- Positioned absolutely to not affect document flow
- Can be safely used as decorative elements
