# Dithered logo

An SVG or PNG logo redrawn on a pixel grid: exact edges, a dithered fill inside, and an optional shimmer or scan line.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. The dithercn agent skill, for building any dither on the engine, is at [/.well-known/agent-skills/dithercn/SKILL.md](/.well-known/agent-skills/dithercn/SKILL.md).

> **This is an example, not the only option.** It is one component built on the dithercn engine. Install it when it is what you were asked for. For any other look, don't stretch its props to fit: write your own field on `DitherShader` ([Write your own dither](/docs/engine/write-your-own.md)), and read this example's source for technique. Its full source is in [https://dithercn.dev/r/dithered-logo.json](https://dithercn.dev/r/dithered-logo.json), under `files[].content`.

## Installation [#installation]

```bash
npx shadcn@latest add https://dithercn.dev/r/dithered-logo.json
```

## Usage [#usage]

```tsx
import { DitheredLogo } from "@/components/dithercn/dithered-logo";

export function Brand() {
  return <DitheredLogo src="/logo.svg" alt="Acme" className="h-8" />;
}
```

Set a height with `className`; the width follows the logo's own ratio. The logo is drawn on a grid of whole device pixels and cut at half coverage, so every edge lands on a cell boundary instead of fraying into noise. A solid outline one cell wide keeps the shapes exact, and the inside takes the `fill`: a gradient that thins towards the bottom, dots, hatching, or solid ink.

By default every part of the logo becomes one ink, `color`. With `tone="original"` it keeps the file's own colours.

## Examples [#examples]

### One treatment for many logos [#one-treatment-for-many-logos]

Logos from different brands, drawn with the same fill and colour, read as one set. Here the hatched fill in grey.



### Colour [#colour]

The same three-colour mark with `tone="original"`, and in one palette colour.

```tsx title="examples/dithered-logo-colour.tsx"
import { DitheredLogo } from "@/components/dithercn/dithered-logo";

// A three-colour mark, inline so the example needs no extra file.
const PRISM = `data:image/svg+xml,${encodeURIComponent(
  `<svg xmlns="http://www.w3.org/2000/svg" width="120" height="104" viewBox="0 0 120 104"><path d="M60 0 120 104H0z" fill="#ff6b3d"/><path d="M60 34 96 98H24z" fill="#ffd23d"/><path d="M60 64 78 98H42z" fill="#3d8bff"/></svg>`
)}`;

export default function DitheredLogoColour() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-12">
      <figure className="flex flex-col items-center gap-3">
        <DitheredLogo
          src={PRISM}
          alt="Prism, in its own colours"
          ratio={120 / 104}
          tone="original"
          cell={2}
          fill="gradient"
          floor={0.15}
          className="h-28"
        />
        <figcaption className="text-muted-foreground font-mono text-xs">
          tone=&quot;original&quot;
        </figcaption>
      </figure>
      <figure className="flex flex-col items-center gap-3">
        <DitheredLogo
          src={PRISM}
          alt="Prism, in green ink"
          ratio={120 / 104}
          color="green"
          cell={2}
          fill="gradient"
          floor={0.15}
          className="h-28"
        />
        <figcaption className="text-muted-foreground font-mono text-xs">
          color=&quot;green&quot;
        </figcaption>
      </figure>
    </div>
  );
}
```

### Scan line [#scan-line]

A 3px cell turns the wordmark into pixel art. `effect="scan"` runs a bright line down it every `period` seconds and leaves solid ink behind for a moment.

```tsx title="examples/dithered-logo-scan.tsx"
import { DitheredLogo } from "@/components/dithercn/dithered-logo";

export default function DitheredLogoScan() {
  return (
    <div className="flex w-full max-w-md flex-col items-center gap-6 rounded-2xl border bg-black px-8 py-12">
      <DitheredLogo
        src="/examples/logos/vantor.svg"
        alt="Vantor"
        ratio={152 / 40}
        cell={3}
        fill="dotted"
        effect="scan"
        period={4}
        color="green"
        className="h-20 max-w-full"
      />
      <p className="font-mono text-xs text-neutral-400">Booting Vantor OS…</p>
    </div>
  );
}
```

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `src` (required) | `string` |  | SVG or PNG URL. Files from another origin need CORS headers. |
| `alt` (required) | `string` |  | The brand name for screen readers. "" hides the logo. |
| `color` | `DitherColor` | `"ink"` | The ink. A palette name or any CSS colour. |
| `tone` | `"mono" \| "original"` | `"mono"` | One ink, or the file's own colours. |
| `fill` | `"gradient" \| "dotted" \| "hatched" \| "solid"` | `"gradient"` | Texture inside the shapes. |
| `outline` | `boolean` | `true` | A solid outline one cell wide, so shapes stay exact with an open fill. |
| `floor` | `number` | `0.3` | Gradient fill: the share of ink left at the bottom of the logo. |
| `matrix` | `"bayer2" \| "bayer4" \| "bayer8" \| "blue-noise"` | `"bayer4"` | Threshold pattern for the gradient fill and the effects. |
| `cell` | `number` | `1` | Size of one cell in CSS pixels. Larger cells give a chunkier, pixel-art mark. |
| `effect` | `"none" \| "shimmer" \| "scan"` | `"none"` | A diagonal band of solid ink, or a bright scan line, sweeping across the logo. |
| `period` | `number` | `6` | Seconds per sweep. |
| `phase` | `number` | `0` | Where in the sweep this logo starts, 0 to 1. Offsets logos in a row. |
| `source` | `"alpha" \| "dark"` | `"alpha"` | "alpha" for transparent backgrounds, "dark" for a dark logo on an opaque light background. |
| `ratio` | `number` | `The logo's ratio` | Width over height. Set it to reserve space before the logo loads. |

## Notes [#notes]

* The root has `role="img"` with the brand name as its label.
* SVGs need a `width` and `height` (or a `viewBox` the browser can size) so the logo has a ratio. SVGs are rasterised by the browser at the exact cell size, so curves stay smooth.
* Effects run at 30 fps only while the logo is on screen, and stop under reduced motion. Without one, the logo is drawn once and redrawn only on resize or theme change.