Cropper

The Cropper component provides interactive image cropping with a draggable stencil, zoom, pan, keyboard navigation, and touch/pinch support.

Import

import { Cropper } from '@we-are-singular/svelte-chop-chop';

Props

Image

PropTypeDefaultDescription
srcImageSourceImage URL, data URL, File, Blob, or HTMLImageElement.

Crop constraints

PropTypeDefaultDescription
aspectRationumber | { min?: number; max?: number } | nullnullLock width/height ratio. null allows free crop.
sizeConstraintsSizeConstraintsObject with minWidth, maxWidth, minHeight, maxHeight, minArea.
cropOutsideImagebooleanfalseAllow the stencil to extend outside the image bounds.
initialCropPartial<Rect>Initial crop rectangle. If omitted, crop fits the image.

Visual

PropTypeDefaultDescription
grid'none' | 'rule-of-thirds' | 'grid' | 'golden-ratio''rule-of-thirds'Grid overlay style on the stencil.
gridOnlyActivebooleantrueOnly show the grid while the stencil is being dragged.
transitionsbooleantrueEnable smooth CSS transitions when the stencil snaps to position.

Stencil

PropTypeDefaultDescription
stencilComponentCropStencilStencil component. Pass CircleStencil for circular crop.
stencilPropsRecord<string, unknown>{}Extra props forwarded to the stencil component.

Interaction

PropTypeDefaultDescription
readOnlybooleanfalseDisable all user interactions (view-only mode).

HTML

PropTypeDefaultDescription
classstring''Extra CSS class on the root element.
stylestring''Inline styles on the root element.

Bindable values

BindingTypeDescription
bind:coordinatesCropCoordinatesTwo-way binding for the current crop coordinates (normalised, pixels, viewport).
bind:transformsTransformStateTwo-way binding for transform state (rotation, flip, zoom, pan).

Events

EventTypeDescription
onchange(c: CropCoordinates) => voidFires whenever the crop region changes.
onready() => voidFires when the image has loaded and the cropper is interactive.
onerror(e: Error) => voidFires when image loading fails.

Snippets

Override default UI regions by passing named snippets:

SnippetPropsDescription
overlayStencilPropsCustom overlay drawn on top of the stencil area.
toolbarCropperReturnCustom toolbar with full access to the cropper instance.
emptyShown when no image source is provided.
loadingShown while the image is loading.
errorErrorShown when image loading fails.

CropCoordinates type

Every coordinate callback and binding provides a CropCoordinates object with three representations of the same crop region:

interface CropCoordinates {
  /** Crop rect relative to original image (0-1 normalised) */
  normalized: Rect;
  /** Crop rect in original image pixels */
  pixels: Rect;
  /** Crop rect relative to the editor viewport */
  viewport: Rect;
}

Stencil types

Use the built-in CropStencil (rectangular) or CircleStencil (circular mask):

<script lang="ts">
  import { Cropper, CircleStencil } from '@we-are-singular/svelte-chop-chop';
</script>

<Cropper src="/avatar.jpg" aspectRatio={1} stencil={CircleStencil} />

Note: CircleStencil automatically forces a 1:1 aspect ratio regardless of the aspectRatio prop.

Export

Bind this to get a reference to the cropper instance and call export():

<script lang="ts">
  import { Cropper } from '@we-are-singular/svelte-chop-chop';
  import type { ExportResult } from '@we-are-singular/svelte-chop-chop';

  let cropper: Cropper;

  async function save() {
    const result: ExportResult = await cropper.export({
      format: 'image/webp',
      quality: 0.92,
      maxWidth: 1200,
    });

    // result.blob    — the exported Blob
    // result.file    — a File object (for FormData uploads)
    // result.dataURL — base64 data URL string
    // result.canvas  — the HTMLCanvasElement used for rendering
    // result.coordinates — CropCoordinates
    // result.transforms  — TransformState
    // result.originalSize — { width, height }

    const url = URL.createObjectURL(result.blob!);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'cropped.webp';
    a.click();
  }
</script>

<Cropper bind:this={cropper} src="/photo.jpg" />
<button onclick={save}>Download</button>

ExportResult type

interface ExportResult {
  canvas?: HTMLCanvasElement;
  blob?: Blob;
  file?: File;
  dataURL?: string;
  coordinates: CropCoordinates;
  transforms: TransformState;
  originalSize: Size;
}

Presets

Spread a preset to preconfigure the Cropper for common use cases:

<script lang="ts">
  import { Cropper } from '@we-are-singular/svelte-chop-chop';
  import { profilePicture } from '@we-are-singular/svelte-chop-chop/presets';
</script>

<Cropper src="/photo.jpg" {...profilePicture} />

Available presets: profilePicture (1:1, 512px), coverPhoto (16:9, min 1200px), productImage (1:1, PNG).

Keyboard shortcuts

When the cropper container is focused:

KeyAction
Arrow keysMove stencil 1px (10px with Shift)
+ / -Zoom in / out
0Reset zoom (fit to view)
EscapeReset crop to fit image

Custom stencil

See the Custom Stencil guide for details on writing your own stencil component.