Image Cropper
Crop and transform images with zoom, rotation, and aspect ratio controls.
Anatomy
<ImageCropper.Root>
<ImageCropper.Viewport>
<ImageCropper.Image />
<ImageCropper.Selection>
<ImageCropper.Handle />
<ImageCropper.Grid />
</ImageCropper.Selection>
</ImageCropper.Viewport>
</ImageCropper.Root>
Examples
Basic
Set up a basic image cropper. Drag the handles to resize the selection, or drag inside to pan the image.
Aspect Ratio
Lock the crop area to a specific aspect ratio. Use the aspectRatio prop—pass a number like 16/9 for widescreen or
1 for square.
Circle Crop
Use cropShape="circle" for profile pictures or avatars. The selection becomes a circle instead of a rectangle.
Initial Crop
Start with a pre-defined crop area using the initialCrop prop. Pass an object with x, y, width, and height in
pixels.
Controlled Zoom
Control zoom programmatically with the zoom and onZoomChange props. Useful when you want external buttons to zoom in
and out.
Zoom Limits
Set minZoom and maxZoom to constrain how far users can zoom. Prevents over-zooming or zooming out past the image
bounds.
Rotation
Rotate the image with the rotation and onRotationChange props. Values are in degrees—common increments are 90
or 180.
Flip
Flip the image horizontally or vertically using the flip prop. Pass an object with horizontal and vertical
booleans.
Min and Max Size
Constrain the crop area size with minWidth, minHeight, maxWidth, and maxHeight. Keeps the selection within
sensible bounds.
Fixed Crop Area
Set fixedCropArea to true when the crop area should stay fixed while the image moves underneath. Useful for
overlay-style cropping.
Crop Preview
Use getCroppedImage() from the context to get the cropped result. Call it with { output: 'dataUrl' } for a base64
string you can use in an img src.
Reset
The context exposes a reset() method that restores the image to its initial state. Handy for an "undo" or "start over"
button.
Events
Listen to onCropChange and onZoomChange to track crop position and zoom level. Use these to sync with external state
or show live previews.
Context
Use ImageCropper.Context to access the cropper API from anywhere inside the root. You get methods like zoomBy,
rotateBy, and setZoom.
Root Provider
Use RootProvider with useImageCropper when you need to control the cropper from outside the component tree. Build
custom toolbars or integrate with form state.
API Reference
Props
Root
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
aspectRatio | numberThe aspect ratio to maintain for the crop area (width / height). For example, an aspect ratio of 16 / 9 will maintain a width to height ratio of 16:9. If not provided, the crop area can be freely resized. | |
cropShape | 'rectangle' | 'circle' | 'rectangle'The shape of the crop area. |
defaultFlip | { horizontal: false, vertical: false } | FlipStateThe initial flip state to apply to the image. |
defaultRotation | 0 | numberThe initial rotation to apply to the image in degrees. |
defaultZoom | 1 | numberThe initial zoom factor to apply to the image. |
fixedCropArea | false | booleanWhether the crop area is fixed in size and position. |
flip | FlipStateThe controlled flip state of the image. | |
ids | Partial<{
root: string
viewport: string
image: string
selection: string
handle: (position: string) => string
}>The ids of the image cropper elements | |
initialCrop | RectThe initial rectangle of the crop area. If not provided, a smart default will be computed based on viewport size and aspect ratio. | |
maxHeight | Infinity | numberThe maximum height of the crop area |
maxWidth | Infinity | numberThe maximum width of the crop area |
maxZoom | 5 | numberThe maximum zoom factor allowed. |
minHeight | 40 | numberThe minimum height of the crop area |
minWidth | 40 | numberThe minimum width of the crop area |
minZoom | 1 | numberThe minimum zoom factor allowed. |
nudgeStep | 1 | numberThe base nudge step for keyboard arrow keys (in pixels). |
nudgeStepCtrl | 50 | numberThe nudge step when Ctrl/Cmd key is held (in pixels). |
nudgeStepShift | 10 | numberThe nudge step when Shift key is held (in pixels). |
onCropChange | (details: CropChangeDetails) => voidCallback fired when the crop area changes. | |
onFlipChange | (details: FlipChangeDetails) => voidCallback fired when the flip state changes. | |
onRotationChange | (details: RotationChangeDetails) => voidCallback fired when the rotation changes. | |
onZoomChange | (details: ZoomChangeDetails) => voidCallback fired when the zoom level changes. | |
rotation | numberThe controlled rotation of the image in degrees (0 - 360). | |
translations | IntlTranslationsSpecifies the localized strings that identify accessibility elements and their states. | |
zoom | numberThe controlled zoom level of the image. | |
zoomSensitivity | 2 | numberControls how responsive pinch-to-zoom is. |
zoomStep | 0.1 | numberThe amount of zoom applied per wheel step. |
| Attribute | Description |
|---|---|
[data-scope] | image-cropper |
[data-part] | root |
[data-fixed] | |
[data-shape] | |
[data-pinch] | |
[data-dragging] | Present when in the dragging state |
[data-panning] |
| CSS Variable | Description |
|---|---|
--crop-width | The width of the Root |
--crop-height | The height of the Root |
--crop-x | The crop x value for the Root |
--crop-y | The crop y value for the Root |
--image-zoom | The image zoom value for the Root |
--image-rotation | The image rotation value for the Root |
--image-offset-x | The offset position for image |
--image-offset-y | The offset position for image |
Grid
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
axis | 'horizontal' | 'vertical'The axis of the grid lines to display | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | image-cropper |
[data-part] | grid |
[data-axis] | The axis to resize |
[data-dragging] | Present when in the dragging state |
[data-panning] |
Handle
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
position | HandlePositionThe position of the handle | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | image-cropper |
[data-part] | handle |
[data-position] | |
[data-disabled] | Present when disabled |
Image
Renders a <img> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | image-cropper |
[data-part] | image |
[data-ready] | |
[data-flip-horizontal] | |
[data-flip-vertical] |
RootProvider
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
value | UseImageCropperReturn | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Selection
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | image-cropper |
[data-part] | selection |
[data-disabled] | Present when disabled |
[data-shape] | |
[data-measured] | |
[data-dragging] | Present when in the dragging state |
[data-panning] |
Viewport
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | image-cropper |
[data-part] | viewport |
[data-disabled] | Present when disabled |
Context
API
| Property | Type |
|---|---|
zoom | numberThe current zoom level of the image. |
rotation | numberThe current rotation of the image in degrees. |
flip | FlipStateThe current flip state of the image. |
crop | RectThe current crop area rectangle in viewport coordinates. |
offset | PointThe current offset (pan position) of the image. |
naturalSize | SizeThe natural (original) size of the image. |
viewportRect | BoundingRectThe viewport rectangle dimensions and position. |
dragging | booleanWhether the crop area is currently being dragged. |
panning | booleanWhether the image is currently being panned. |
setZoom | (zoom: number) => voidFunction to set the zoom level of the image. |
zoomBy | (delta: number) => voidFunction to zoom the image by a relative amount. |
setRotation | (rotation: number) => voidFunction to set the rotation of the image. |
rotateBy | (degrees: number) => voidFunction to rotate the image by a relative amount in degrees. |
setFlip | (flip: Partial<FlipState>) => voidFunction to set the flip state of the image. |
flipHorizontally | (value?: boolean) => voidFunction to flip the image horizontally. Pass a boolean to set explicitly or omit to toggle. |
flipVertically | (value?: boolean) => voidFunction to flip the image vertically. Pass a boolean to set explicitly or omit to toggle. |
resize | (handlePosition: HandlePosition, delta: number) => voidFunction to resize the crop area from a handle programmatically. |
reset | () => voidFunction to reset the cropper to its initial state. |
getCroppedImage | (options?: GetCroppedImageOptions) => Promise<string | Blob>Function to get the cropped image with all transformations applied. Returns a Promise that resolves to either a Blob or data URL. |
getCropData | () => CropDataFunction to get the crop data in natural image pixel coordinates. These coordinates are relative to the original image dimensions, accounting for zoom, rotation, and flip transformations. Use this for server-side cropping or state persistence. |