{"id":24567614,"url":"https://github.com/dominictobias/react-image-crop","last_synced_at":"2025-05-13T21:02:59.836Z","repository":{"id":39351728,"uuid":"43984013","full_name":"dominictobias/react-image-crop","owner":"dominictobias","description":"A responsive image cropping tool for React","archived":false,"fork":false,"pushed_at":"2025-04-14T13:11:42.000Z","size":10655,"stargazers_count":3962,"open_issues_count":69,"forks_count":344,"subscribers_count":27,"default_branch":"master","last_synced_at":"2025-05-06T02:03:00.709Z","etag":null,"topics":["crop-image","javascript","react","responsive"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dominictobias.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"dominictobias","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2015-10-09T22:57:05.000Z","updated_at":"2025-05-01T13:21:39.000Z","dependencies_parsed_at":"2023-11-21T00:44:31.969Z","dependency_job_id":"6aad68c2-3840-43e3-8a6e-df3e228ea99b","html_url":"https://github.com/dominictobias/react-image-crop","commit_stats":{"total_commits":644,"total_committers":78,"mean_commits":8.256410256410257,"dds":0.2996894409937888,"last_synced_commit":"ec2e9e11737ac86559480fbee44fec6cbd638439"},"previous_names":["sekoyo/react-image-crop","dominictobias/react-image-crop"],"tags_count":164,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictobias%2Freact-image-crop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictobias%2Freact-image-crop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictobias%2Freact-image-crop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictobias%2Freact-image-crop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dominictobias","download_url":"https://codeload.github.com/dominictobias/react-image-crop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252606964,"owners_count":21775415,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crop-image","javascript","react","responsive"],"created_at":"2025-01-23T14:00:39.502Z","updated_at":"2025-05-06T02:03:22.416Z","avatar_url":"https://github.com/dominictobias.png","language":"TypeScript","funding_links":["https://github.com/sponsors/dominictobias"],"categories":["TypeScript"],"sub_categories":[],"readme":"# React Image Crop\n\nAn image cropping tool for React with no dependencies.\n\n[![React Image Crop on NPM](https://img.shields.io/npm/v/react-image-crop.svg)](https://www.npmjs.com/package/react-image-crop)\n\n[CodeSandbox Demo](https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o)\n\n![ReactCrop GIF](https://raw.githubusercontent.com/dominictobias/react-image-crop/master/crop-demo.gif)\n\n## Table of Contents\n\n1. [Features](#features)\n2. [Installation](#installation)\n3. [Usage](#usage)\n4. [Example](#example)\n5. [CDN](#cdn)\n6. [Props](#props)\n7. [FAQ](#faq)\n   1. [How can I generate a crop preview in the browser?](#how-can-i-generate-a-crop-preview-in-the-browser)\n   2. [How to correct image EXIF orientation/rotation?](#how-to-correct-image-exif-orientationrotation)\n   3. [How to filter, rotate and annotate?](#how-to-filter-rotate-and-annotate)\n   4. [How can I center the crop?](#how-can-i-center-the-crop)\n8. [Contributing / Developing](#contributing--developing)\n\n## Features\n\n- Responsive (you can use pixels or percentages).\n- Touch enabled.\n- Free-form or fixed aspect crops.\n- Fully keyboard accessible (a11y).\n- No dependencies/small footprint (\u003c5KB gzip).\n- Min/max crop size.\n- Crop anything, not just images.\n\nIf React Crop doesn't cover your requirements then take a look at [Pintura](https://pqina.nl/pintura/?ref=react-image-crop) (our sponsor). It features cropping, rotating, filtering, annotation, and lots more.\n\n[Learn more about Pintura here](https://pqina.nl/pintura/?ref=react-image-crop)\n\n## Installation\n\n```\nnpm i react-image-crop --save\nyarn add react-image-crop\npnpm add react-image-crop\n```\n\nThis library works with all modern browsers. It does not work with IE.\n\n## Usage\n\nInclude the main js module:\n\n```js\nimport ReactCrop from 'react-image-crop'\n```\n\nInclude either `dist/ReactCrop.css` or `ReactCrop.scss`.\n\n```js\nimport 'react-image-crop/dist/ReactCrop.css'\n// or scss:\nimport 'react-image-crop/src/ReactCrop.scss'\n```\n\n## Example\n\n```tsx\nimport ReactCrop, { type Crop } from 'react-image-crop'\n\nfunction CropDemo({ src }) {\n  const [crop, setCrop] = useState\u003cCrop\u003e()\n  return (\n    \u003cReactCrop crop={crop} onChange={c =\u003e setCrop(c)}\u003e\n      \u003cimg src={src} /\u003e\n    \u003c/ReactCrop\u003e\n  )\n}\n```\n\nSee the [sandbox demo](https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o) for a more complete example.\n\n## CDN\n\n```html\n\u003clink href=\"https://unpkg.com/react-image-crop/dist/ReactCrop.css\" rel=\"stylesheet\" /\u003e\n\u003cscript src=\"https://unpkg.com/react-image-crop/dist/index.umd.cjs\"\u003e\u003c/script\u003e\n```\n\nNote when importing the script globally using a `\u003cscript\u003e` tag access the component with `ReactCrop.Component`.\n\n## Props\n\n**`onChange: (crop: PixelCrop, percentCrop: PercentCrop) =\u003e void`**\n\nA callback which happens for every change of the crop (i.e. many times as you are dragging/resizing). Passes the current crop state object.\n\nNote you _must_ implement this callback and update your crop state, otherwise nothing will change!\n\n```tsx\n\u003cReactCrop crop={crop} onChange={(crop, percentCrop) =\u003e setCrop(crop)} /\u003e\n```\n\n`crop` and `percentCrop` are interchangeable. `crop` uses pixels and `percentCrop` uses percentages to position and size itself. Percent crops are resistant to image/media resizing.\n\n**`crop?: Crop`**\n\nStarting with no crop:\n\n```tsx\nconst [crop, setCrop] = useState\u003cCrop\u003e()\n\n\u003cReactCrop crop={crop} onChange={c =\u003e setCrop(c)}\u003e\n  \u003cimg src={src} /\u003e\n\u003c/ReactCrop\u003e\n```\n\nStarting with a preselected crop:\n\n```tsx\nconst [crop, setCrop] = useState\u003cCrop\u003e({\n  unit: '%', // Can be 'px' or '%'\n  x: 25,\n  y: 25,\n  width: 50,\n  height: 50\n})\n\n\u003cReactCrop crop={crop} onChange={c =\u003e setCrop(c)}\u003e\n  \u003cimg src={src} /\u003e\n\u003c/ReactCrop\u003e\n```\n\n⚠️ You must ensure the crop is in bounds and correct to the aspect ratio if manually setting. Aspect ratios can be tricky when using %. You can make use of `centerCrop` and `makeAspectCrop` helpers. See [How can I center the crop?](#how-can-i-center-the-crop) or the [CodeSanbox Demo](https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o) for examples.\n\n**`aspect?: number`**\n\nThe aspect ratio of the crop, e.g. `1` for a square or `16 / 9` for landscape. Omit/pass undefined for a free-form crop.\n\n**`minWidth?: number`**\n\nA minimum crop width, in pixels.\n\n**`minHeight?: number`**\n\nA minimum crop height, in pixels.\n\n**`maxWidth?: number`**\n\nA maximum crop width, in pixels.\n\n**`maxHeight?: number`**\n\nA maximum crop height, in pixels.\n\n**`keepSelection?: boolean`**\n\nIf true is passed then selection can't be disabled if the user clicks outside the selection area.\n\n**`disabled?: boolean`**\n\nIf true then the user cannot resize or draw a new crop. A class of `ReactCrop--disabled` is also added to the container for user styling.\n\n**`locked?: boolean`**\n\nIf true then the user cannot create or resize a crop, but can still drag the existing crop around. A class of `ReactCrop--locked` is also added to the container for user styling.\n\n**`className?: string`**\n\nA string of classes to add to the main `ReactCrop` element.\n\n**`style?: React.CSSProperties`**\n\nInline styles object to be passed to the image wrapper element.\n\n**`onComplete?: (crop: PixelCrop, percentCrop: PercentCrop) =\u003e void`**\n\nA callback which happens after a resize, drag, or nudge. Passes the current crop state object.\n\n`percentCrop` is the crop as a percentage. A typical use case for it would be to save it so that the user's crop can be restored regardless of the size of the image (for example saving it on desktop, and then using it on a mobile where the image is smaller).\n\n**`onDragStart?: (e: PointerEvent) =\u003e void`**\n\nA callback which happens when a user starts dragging or resizing. It is convenient to manipulate elements outside this component.\n\n**`onDragEnd?: (e: PointerEvent) =\u003e void`**\n\nA callback which happens when a user releases the cursor or touch after dragging or resizing.\n\n**`renderSelectionAddon?: (state: ReactCropState) =\u003e React.ReactNode`**\n\nRender a custom element inside the crop selection.\n\n**`ruleOfThirds?: boolean`**\n\nShow [rule of thirds](https://en.wikipedia.org/wiki/Rule_of_thirds) lines in the cropped area. Defaults to `false`.\n\n**`circularCrop?: boolean`**\n\nShow the crop area as a circle. If your `aspect` is not `1` (a square) then the circle will be warped into an oval shape. Defaults to `false`.\n\n## FAQ\n\n### How can I generate a crop preview in the browser?\n\nThis isn't part of the library but there is an example over here [CodeSandbox Demo](https://codesandbox.io/s/react-image-crop-demo-with-react-hooks-y831o).\n\n### How to correct image EXIF orientation/rotation?\n\nYou might find that some images are rotated incorrectly. Unfortunately this is a browser wide issue not related to this library. You need to fix your image before passing it in.\n\nYou can use the following library to load images, which will correct the rotation for you: https://github.com/blueimp/JavaScript-Load-Image/\n\nYou can read an issue on this subject here: https://github.com/dominictobias/react-image-crop/issues/181\n\nIf you're looking for a complete out of the box image editor which already handles EXIF rotation then consider using [Pintura](https://pqina.nl/pintura/?ref=react-image-crop).\n\n\u003ch3\u003eHow to filter, rotate and annotate?\u003c/h3\u003e\n\nThis library is deliberately lightweight and minimal for you to build features on top of. If you wish to perform more advanced image editing out of the box then consider using [Pintura](https://pqina.nl/pintura/?ref=react-image-crop).\n\n![Pintura Demo](https://raw.githubusercontent.com/DominicTobias/react-image-crop/master/doka-demo.gif)\n\n### How can I center the crop?\n\nThe easiest way is to use the percentage unit:\n\n```js\ncrop: {\n  unit: '%',\n  width: 50,\n  height: 50,\n  x: 25,\n  y: 25\n}\n```\n\nCentering an aspect ratio crop is trickier especially when dealing with `%`. However two helper functions are provided:\n\n1. Listen to the load event of your media to get its size:\n\n```jsx\n\u003cReactCrop crop={crop} aspect={16 / 9}\u003e\n  \u003cimg src={src} onLoad={onImageLoad} /\u003e\n\u003c/ReactCrop\u003e\n```\n\n2. Use `makeAspectCrop` to create your desired aspect and then `centerCrop` to center it:\n\n```js\nfunction onImageLoad(e) {\n  const { naturalWidth: width, naturalHeight: height } = e.currentTarget\n\n  const crop = centerCrop(\n    makeAspectCrop(\n      {\n        // You don't need to pass a complete crop into\n        // makeAspectCrop or centerCrop.\n        unit: '%',\n        width: 90,\n      },\n      16 / 9,\n      width,\n      height\n    ),\n    width,\n    height\n  )\n\n  setCrop(crop)\n}\n```\n\nAlso remember to set your crop using the percentCrop on changes:\n\n```js\nconst onCropChange = (crop, percentCrop) =\u003e setCrop(percentCrop)\n```\n\nAnd your `aspect` prop should be set to the same value: `\u003cReactCrop aspect={16 / 9} ... /\u003e`.\n\n## Contributing / Developing\n\nTo develop run `pnpm install \u0026\u0026 pnpm dev` and open the localhost server in your browser. Update code and it will reload. When you're ready, open a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominictobias%2Freact-image-crop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdominictobias%2Freact-image-crop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominictobias%2Freact-image-crop/lists"}