Cropper.js: JavaScript Image Cropper with Zoom & Rotate

Category: Image , Javascript , Recommended | August 24, 2026
Authorfengyuanchen
Last UpdateAugust 24, 2026
LicenseMIT
Views24,417 views
Cropper.js: JavaScript Image Cropper with Zoom & Rotate

Cropper.js is a JavaScript image cropping library for adding an interactive crop area to images in the browser. You can drag and resize the crop box, move or rotate the image, zoom, flip, and export the selected region to a canvas.

The latest Cropper.js library (v2.x+) builds the editor from Web Components. Crop geometry lives on <cropper-selection>, image transforms live on <cropper-image>, and pointer actions run through <cropper-canvas>.

The main cropperjs package includes the standard component set, while individual @cropper/* packages are available for custom builds.

Features:

  • Draggable and resizable crop selections.
  • Fixed and free aspect ratios.
  • Touch, pointer, and keyboard interaction.
  • Image move, rotate, zoom, scale, flip, and skew controls.
  • Multiple selections on one source image.
  • Canvas export for the selected image area.
  • Custom cropper templates.
  • CSS-in-JS styles for the Web Components.
  • On-demand imports for individual cropper elements.

How To Use Cropper.js

Install Cropper.js

Install the main package from npm.

npm install cropperjs

Basic Usage

The cropper requires an image and enough container height for the editing area. Import Cropper, then pass the image element or a selector to the constructor.

<div class="photo-cropper">
  <img id="photo" src="photo.jpg" alt="Photo to crop">
</div>
<style>
.photo-cropper {
  width: 100%;
  max-width: 720px;
  height: 420px;
}
.photo-cropper cropper-canvas {
  height: 100%;
}
</style>
import Cropper from 'cropperjs';
const cropper = new Cropper('#photo');

CDN Setup

You can also directly load the browser build in your document.

<script src="https://unpkg.com/[email protected]/dist/cropper.js"></script>
<script>
  const cropper = new Cropper('#photo');
</script>

Export The Cropped Image

The crop rectangle belongs to <cropper-selection>. Call $toCanvas() on that element when you need the selected pixels as a native <canvas>.

<button id="crop-button" type="button">Crop Image</button>
<img id="crop-result" alt="Cropped result">
const selection = cropper.getCropperSelection();
const resultImage = document.querySelector('#crop-result');
document.querySelector('#crop-button').addEventListener('click', async () => {
  if (!selection) return;
  const canvas = await selection.$toCanvas();
  canvas.toBlob((blob) => {
    if (!blob) return;
    resultImage.src = URL.createObjectURL(blob);
  }, 'image/jpeg', 0.9);
});

Set A Fixed Aspect Ratio

Set aspectRatio on the active selection for crops such as square avatars or 16:9 banners.

const selection = cropper.getCropperSelection();
if (selection) {
  selection.aspectRatio = 16 / 9;
}

Set The Crop Position And Size

The selection exposes x, y, width, and height. $change() updates those values in one call.

const selection = cropper.getCropperSelection();
if (selection) {
  selection.$change(40, 30, 320, 180);
}

Move, Rotate, Zoom, And Flip The Image

Get <cropper-image> when you need to change the source image under the crop box. Its methods control movement, rotation, zoom, scaling, flipping, skewing, and transform matrices.

const cropperImage = cropper.getCropperImage();
if (cropperImage) {
  cropperImage.$move(20, 10);
  cropperImage.$rotate('90deg');
  cropperImage.$zoom(0.1);
  cropperImage.$scale(-1, 1); // Flip horizontally.
}

Reset The Image And Crop Selection

A reset action usually needs to restore both the image transform and the crop rectangle.

const cropperImage = cropper.getCropperImage();
const selection = cropper.getCropperSelection();
cropperImage?.$resetTransform();
selection?.$reset();

Build The Cropper UI With Web Components

Importing cropperjs registers the bundled Cropper elements automatically. Direct component markup keeps each canvas, image, selection, and handle available through the DOM.

import 'cropperjs';
<cropper-canvas background>
  <cropper-image
    src="photo.jpg"
    alt="Photo to crop"
    rotatable
    scalable
    skewable
    translatable>
  </cropper-image>
  <cropper-shade hidden></cropper-shade>
  <cropper-handle action="select" plain></cropper-handle>
  <cropper-selection initial-coverage="0.5" movable resizable>
    <cropper-grid role="grid" covered></cropper-grid>
    <cropper-crosshair centered></cropper-crosshair>
    <cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
    <cropper-handle action="n-resize"></cropper-handle>
    <cropper-handle action="e-resize"></cropper-handle>
    <cropper-handle action="s-resize"></cropper-handle>
    <cropper-handle action="w-resize"></cropper-handle>
    <cropper-handle action="ne-resize"></cropper-handle>
    <cropper-handle action="nw-resize"></cropper-handle>
    <cropper-handle action="se-resize"></cropper-handle>
    <cropper-handle action="sw-resize"></cropper-handle>
  </cropper-selection>
</cropper-canvas>

Import Cropper Elements On Demand

Custom builds can install the element packages they actually use. Register each imported class with $define() before its custom element appears in the DOM.

npm install @cropper/element-canvas @cropper/element-image @cropper/element-selection
import CropperCanvas from '@cropper/element-canvas';
import CropperImage from '@cropper/element-image';
import CropperSelection from '@cropper/element-selection';
CropperCanvas.$define();
CropperImage.$define();
CropperSelection.$define();

Use A Custom Cropper Template

The template constructor option replaces the built-in component tree. Define the image, selection, handles, and other controls that the editor should render.

const cropper = new Cropper('#photo', {
  template: `
    <cropper-canvas background>
      <cropper-image rotatable scalable translatable></cropper-image>
      <cropper-shade hidden></cropper-shade>
      <cropper-handle action="select" plain></cropper-handle>
      <cropper-selection initial-coverage="0.6" movable resizable>
        <cropper-grid role="grid" covered></cropper-grid>
        <cropper-crosshair centered></cropper-crosshair>
        <cropper-handle action="move"></cropper-handle>
        <cropper-handle action="se-resize"></cropper-handle>
      </cropper-selection>
    </cropper-canvas>
  `
});

Core API Reference

After initialization, use the Cropper instance to access the canvas, image, and selection elements. Their properties and methods control the crop state.

Cropper Constructor Options

  • container (Element | string): Sets the Cropper container. The source element’s parent is used by default, with document.body as the fallback.
  • template (string): Replaces the built-in Cropper template.

Cropper Instance Properties

  • element (HTMLImageElement | HTMLCanvasElement): The normalized image or canvas passed to the constructor.
  • options (Object): The normalized constructor options.
  • container (Element): The normalized Cropper container.

Cropper Instance Methods

// Return the <cropper-canvas> element.
cropper.getCropperCanvas();
// Return the <cropper-image> element.
cropper.getCropperImage();
// Return the first <cropper-selection> element.
cropper.getCropperSelection();
// Return all <cropper-selection> elements.
cropper.getCropperSelections();
// Destroy the Cropper instance.
cropper.destroy();

CropperSelection Properties

  • x (number, default 0): Horizontal coordinate of the selection.
  • y (number, default 0): Vertical coordinate of the selection.
  • width (number, default 0): Selection width.
  • height (number, default 0): Selection height.
  • aspectRatio (number, default NaN): Fixed width-to-height ratio.
  • initialAspectRatio (number, default NaN): Ratio used when the initial selection is created.
  • initialCoverage (number, default NaN): Initial crop coverage from 0 to 1.
  • dynamic (boolean, default false): Keeps the selection geometry in sync with image changes.
  • movable (boolean, default false): Turns on drag movement for the selection.
  • resizable (boolean, default false): Turns on resize handles for the selection.
  • zoomable (boolean, default false): Lets zoom actions change the selection size.
  • multiple (boolean, default false): Turns on multiple selections.
  • keyboard (boolean, default false): Adds keyboard controls to the active selection.
  • outlined (boolean, default false): Displays an outline around the selection.
  • precise (boolean, default false): Retains decimal values for x, y, width, and height.

CropperSelection Keyboard Controls

Set keyboard to true when the active selection should respond to these keys.

  • Delete or Command + Backspace: Removes the active selection.
  • ArrowLeft, ArrowRight, ArrowUp, ArrowDown: Moves the selection by 1 pixel.
  • +: Zooms the selection in by 10%.
  • -: Zooms the selection out by 10%.

CropperSelection Methods

// Center the selection inside its parent.
selection.$center();
// Move by an offset.
selection.$move(20, 10);
// Move to exact coordinates.
selection.$moveTo(80, 60);
// Resize from a side or corner.
selection.$resize('se-resize', 30, 20);
// Zoom the selection around its center.
selection.$zoom(0.1);
// Set position and size in one call.
selection.$change(40, 30, 320, 180);
// Restore the initial selection.
selection.$reset();
// Clear the selection.
selection.$clear();
// Refresh the rendered position and size.
selection.$render();
// Export the selected area to a canvas.
const croppedCanvas = await selection.$toCanvas();
// Export at a requested canvas size and adjust drawing before output.
const resizedCanvas = await selection.$toCanvas({
  width: 640,
  height: 360,
  beforeDraw(context) {
    context.imageSmoothingQuality = 'high';
  }
});

CropperImage Properties

  • initialFit (string, default contain): Initial image size when centered in its parent. Accepted values are cover, fill, contain, scale-down, and none.
  • maxFit (string, default empty): Maximum image size relative to the parent.
  • minFit (string, default empty): Minimum image size relative to the parent.
  • rotatable (boolean, default false): Permits image rotation.
  • scalable (boolean, default false): Permits image scaling.
  • skewable (boolean, default false): Permits skew transforms.
  • slottable (boolean, default false): Turns on the default slot.
  • translatable (boolean, default false): Permits image translation.
  • initialCenterSize (string, default contain): Deprecated in 2.2.0. Use initialFit.

CropperImage Methods

// Wait for the source image to load.
await cropperImage.$ready();
// Center the image and choose its centered size.
cropperImage.$center('contain');
// Move by an offset.
cropperImage.$move(20, 10);
// Move to exact coordinates.
cropperImage.$moveTo(80, 60);
// Rotate around the image center.
cropperImage.$rotate('45deg');
// Zoom in or out. The second and third arguments can set the zoom origin.
cropperImage.$zoom(0.1);
cropperImage.$zoom(-0.1);
// Scale or flip the image.
cropperImage.$scale(1.1);
cropperImage.$scale(-1, 1);
// Skew the image.
cropperImage.$skew('10deg', 0);
// Translate the image.
cropperImage.$translate(20, 10);
// Multiply the current transformation matrix.
cropperImage.$transform(1, 0, 0, 1, 20, 10);
// Replace the current transformation matrix.
cropperImage.$setTransform([1, 0, 0, 1, 20, 10]);
// Read the current transformation matrix.
const matrix = cropperImage.$getTransform();
// Restore the identity transformation matrix.
cropperImage.$resetTransform();

CropperCanvas Properties

  • background (boolean, default false): Displays the grid background.
  • disabled (boolean, default false): Blocks pointer interaction on the canvas.
  • scaleStep (number, default 0.1): Wheel zoom step.
  • themeColor (string, default #39f): Primary color used by the canvas and its child elements.

CropperCanvas Methods

const cropperCanvas = cropper.getCropperCanvas();
// Change the active interaction action.
cropperCanvas?.$setAction('move');
// Render the cropper canvas to a native canvas element.
const fullCanvas = await cropperCanvas?.$toCanvas();

Events

Canvas Action Events

<cropper-canvas> fires action, actionstart, actionmove, and actionend during pointer interaction. These events are cancelable. Call event.preventDefault() when an application needs to block the pending action.

const cropperCanvas = cropper.getCropperCanvas();
cropperCanvas?.addEventListener('action', (event) => {
  console.log(event.detail.action);
});
cropperCanvas?.addEventListener('actionstart', (event) => {
  console.log(event.detail.action);
});
cropperCanvas?.addEventListener('actionmove', (event) => {
  console.log(event.detail.action);
});
cropperCanvas?.addEventListener('actionend', (event) => {
  console.log(event.detail.action);
});

Selection Change Event

<cropper-selection> fires change before its position or size changes. The event detail contains x, y, width, and height.

const selection = cropper.getCropperSelection();
selection?.addEventListener('change', (event) => {
  const { x, y, width, height } = event.detail;
  console.log(x, y, width, height);
});

Image Transform And Change Events

<cropper-image> fires transform before its transformation matrix changes. The change event fires before its position or size changes.

const cropperImage = cropper.getCropperImage();
cropperImage?.addEventListener('transform', (event) => {
  console.log(event.detail.matrix, event.detail.oldMatrix);
});
cropperImage?.addEventListener('change', (event) => {
  console.log(event.detail.x, event.detail.y);
  console.log(event.detail.width, event.detail.height);
});

Cropper.js 1.x API Migration

In 2.x, image transforms, crop geometry, preview output, and pointer events moved to the Web Components that own those tasks.

  • aspectRatio maps to <cropper-selection>.aspectRatio.
  • getCroppedCanvas() maps to <cropper-selection>.$toCanvas().
  • setAspectRatio() maps to <cropper-selection>.aspectRatio.
  • move() maps to <cropper-image>.$move().
  • moveTo() maps to <cropper-image>.$moveTo().
  • zoom() maps to <cropper-image>.$scale().
  • zoomTo() maps to <cropper-image>.$setTransform().
  • rotate() maps to <cropper-image>.$rotate().
  • scaleX() and scaleY() map to <cropper-image>.$scale().
  • getData() maps to <cropper-image>.$getTransform() plus the selection’s x, y, width, and height.
  • cropstart, cropmove, and cropend map to actionstart, actionmove, and actionend on <cropper-canvas>.
  • preview maps to <cropper-viewer>.

Alternatives And Related Resources

FAQs

Q: Does Cropper.js require jQuery?
A: No. Cropper.js is a standalone JavaScript image cropper. The jQuery Cropper package wraps Cropper.js 1.x and depends on jQuery.

Q: Does Cropper.js 2.x require a CSS file?
A: No standalone stylesheet is required for the standard 2.x package. The Cropper elements use CSS-in-JS. Page CSS is still useful for container dimensions and project-specific styling.

Q: How do I get the cropped image in Cropper.js 2.x?
A: Get the active <cropper-selection> with cropper.getCropperSelection(), then await selection.$toCanvas(). Use the normal Canvas API to convert the result to a Blob or data URL.

Q: Why does getCroppedCanvas() not work in Cropper.js 2.x?
A: getCroppedCanvas() belongs to the 1.x API. Cropper.js 2.x uses $toCanvas() on <cropper-selection>.

Q: Why is the crop area too small?
A: Give the cropper container or <cropper-canvas> an explicit height that matches the editor layout. The built-in canvas minimum is 200px wide and 100px high.

Changelog

v2.2.0 (08/24/2026)

  • Added initialFit, maxFit, and minFit image sizing controls.
  • Added the change event to <cropper-image>.
  • Added fill, scale-down, and none modes to $center().
  • Added center-based scaling for images and selections.
  • Added cancelable canvas action handling through event.preventDefault().
  • Fixed pointer, touch selection, grid, viewer, and custom-element issues.

v2.1.1 (04/06/2026)

  • Fixed image centering when translation and scaling are disabled.
  • Fixed shade rendering during resize.
  • Fixed SVG preview sizing in Safari.

v2.1.0 (10/19/2025)

  • Added the destroy() method.
  • Fixed selection event handling in Shadow DOM.
  • Improved image and shade rendering.

v2.0.1 (07/25/2025)

  • Fixed package distribution files and image cross-origin attributes.
  • Improved crop selection movement and custom-element container handling.

v2.0.0 (03/01/2025)

  • Released the stable modular Web Components architecture for Cropper.js 2.x.

v1.6.1 (09/17/2023)

  • Bug fixes.

v1.6.0 (08/26/2023)

  • Added the rounded option to the 1.x getCroppedCanvas() method.

v1.5.13 (11/20/2021)

  • Added backface-visibility: hidden to reduce ghost lines while moving the cropper image.
  • Removed the unused cropper-hide class from the cropper image.
  • Checked for a parent node before removing the cropper container.

v1.5.12 (06/12/2021)

  • Fixed responsive behavior when only the cropper height changed.

v1.5.11 (02/17/2021)

  • Fixed TypeScript declaration compatibility.

v1.5.10 (02/14/2021)

  • Set XMLHttpRequest calls to asynchronous mode explicitly.
  • Improved TypeScript declarations.

v1.5.6 (10/29/2019)

  • Improved event type detection for iOS 13+.

You Might Be Interested In:


Leave a Reply