# Image

> An image with lazy loading, a reserved ratio and a graceful fallback.

Category: Media & code · Status: stable · Package: @bindshq/stance-react@0.1.1 · Docs: https://stanceui.com/components/image

Image wraps <img> with lazy loading, asynchronous decoding, rounded corners from tokens and an optional ratio that stops layout shift. When the source fails to load it shows a neutral placeholder that keeps the alt text available to assistive technology.

## Import

```tsx
import { Image } from '@bindshq/stance-react';
```

Styles are imported once per app: `@bindshq/stance-tokens/css` and `@bindshq/stance-react/styles.css`.

## Examples

### Basic

```tsx
import { Image } from '@bindshq/stance-react';

const svg = encodeURIComponent(
  `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180"><rect width="320" height="180" fill="#ECE6DF"/><rect x="24" y="24" width="120" height="14" rx="7" fill="#140C2E"/><rect x="24" y="48" width="200" height="8" rx="4" fill="#817D8C"/><rect x="24" y="64" width="160" height="8" rx="4" fill="#9E9AA3"/><circle cx="270" cy="130" r="34" fill="#140C2E"/></svg>`,
);

const preview = `data:image/svg+xml,${svg}`;

export function Basic() {
  return (
    <Image
      src={preview}
      alt="Email signature preview for Acme Ltd"
      ratio={16 / 9}
      radius="lg"
      bordered
      style={{ width: 320 }}
    />
  );
}
```

### Fallback

A broken source shows a placeholder.

```tsx
import { Image } from '@bindshq/stance-react';

const svg = encodeURIComponent(
  `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180"><rect width="320" height="180" fill="#ECE6DF"/><rect x="24" y="24" width="120" height="14" rx="7" fill="#140C2E"/><rect x="24" y="48" width="200" height="8" rx="4" fill="#817D8C"/><rect x="24" y="64" width="160" height="8" rx="4" fill="#9E9AA3"/><circle cx="270" cy="130" r="34" fill="#140C2E"/></svg>`,
);

const preview = `data:image/svg+xml,${svg}`;

export function Fallback() {
  return (
    <Image
      src="/missing-signature.png"
      alt="Signature preview unavailable"
      ratio={16 / 9}
      style={{ width: 320 }}
    />
  );
}
```

### Radius and border

```tsx
import { Image } from '@bindshq/stance-react';

const svg = encodeURIComponent(
  `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180"><rect width="320" height="180" fill="#ECE6DF"/><rect x="24" y="24" width="120" height="14" rx="7" fill="#140C2E"/><rect x="24" y="48" width="200" height="8" rx="4" fill="#817D8C"/><rect x="24" y="64" width="160" height="8" rx="4" fill="#9E9AA3"/><circle cx="270" cy="130" r="34" fill="#140C2E"/></svg>`,
);

const preview = `data:image/svg+xml,${svg}`;

export function Shapes() {
  return (
    <div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
      <Image src={preview} alt="Square crop" ratio={1} radius="none" style={{ width: 96 }} />
      <Image src={preview} alt="Rounded crop" ratio={1} radius="xl" style={{ width: 96 }} />
      <Image src={preview} alt="Circular crop" ratio={1} radius="full" style={{ width: 96 }} />
    </div>
  );
}
```

## API reference

| Component | Prop | Type | Default | Description |
| --- | --- | --- | --- | --- |
| Image | `alt` (required) | `string` | None | Text alternative; empty for decorative images. |
| Image | `ratio` | `number` | None | Width ÷ height to reserve space. |
| Image | `fit` | `'cover' \| 'contain' \| 'fill' \| 'none'` | `'cover'` | object-fit. |
| Image | `radius` | `'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'md'` | Corner radius. |
| Image | `bordered` | `boolean` | None | Subtle border for screenshots. |
| Image | `fallback` | `ReactNode` | None | Content when loading fails. |

## Accessibility

- alt is required by the type. Pass alt="" for decorative images.
- Fallbacks keep the alt text via role="img".

## Guidelines

**Do**

- Describe what the image conveys, not what it looks like.

**Don’t**

- Embed text in images.

## Related

- https://stanceui.com/components/aspect-ratio
- https://stanceui.com/components/avatar
