A blazing fast, customizable PDF cropper for React. Drag, resize, crop, watermark, preview, and download any region of any PDF—right from your web app.
-
🖼 Drag, resize, and move the selection box with mouse or touch—just like an image editor.
-
💡 Works with any PDF renderer: drop into react-pdf-viewer, your own PDF.js setup, or any HTML canvas-based viewer.
-
⚡ Zero dependency screenshot: Crops directly from PDF.js canvas, no html2canvas needed, no lag.
-
🪄 Add your logo or watermark to any cropped image.
-
💾 Instant download utility: Save your crop with one click.
-
🧩 Fully UI-agnostic: Hide built-in buttons, add your own controls anywhere.
-
🤲 Hooks & external control: All actions (crop, cancel, download) available outside the cropbox.
-
🚀 Production-ready: Used in real-world news, content, and SaaS workflows.
npm install react-pdf-cropper
# or
yarn add react-pdf-cropper
With react-pdf-viewer
import React, { useRef, useState, useCallback } from "react";
import { Worker, Viewer } from "@react-pdf-viewer/core";
import { defaultLayoutPlugin } from "@react-pdf-viewer/default-layout";
import PDFCropperOverlay, { handleDownload, CropPreviewButton, CancelCropButton } from "react-pdf-cropper";
import "@react-pdf-viewer/core/lib/styles/index.css";
import "@react-pdf-viewer/default-layout/lib/styles/index.css";
function App() {
const containerRef = useRef();
const [pdfFile, setPdfFile] = useState("/sample.pdf");
const [croppedImage, setCroppedImage] = useState(null);
const [page, setPage] = useState(1);
const [isCropping, setIsCropping] = useState(false);
const [handlers, setHandlers] = useState({});
// Cropper overlay gives you crop/cancel handlers for your own buttons
const getHandlers = useCallback((handlers) => setHandlers(handlers), []);
return (
<div>
<button onClick={() => setIsCropping(true)} disabled={isCropping}>
Start Cropping
</button>
{isCropping && (
<>
<CancelCropButton onClick={handlers.stopCropping} />
<CropPreviewButton onClick={handlers.handleSaveClick} />
</>
)}
<div ref={containerRef} style={{ position: "relative", width: 800, height: 900 }}>
<Worker workerUrl="https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js">
<Viewer
fileUrl={pdfFile}
plugins={[defaultLayoutPlugin()]}
onPageChange={e => setPage(e.currentPage + 1)}
/>
</Worker>
<PDFCropperOverlay
containerRef={containerRef}
isCropping={isCropping}
setIsCropping={setIsCropping}
currentPage={page}
onCrop={setCroppedImage}
getHandlers={getHandlers}
showDefaultButtons={false} // Use your own buttons!
/>
</div>
{croppedImage && (
<>
<img src={croppedImage} alt="Cropped" style={{ maxWidth: 400, border: "1px solid #ddd" }} />
<button onClick={() => handleDownload(croppedImage)}>
Download Cropped Image
</button>
</>
)}
</div>
);
}
export default App;
Props | Type | Required | Description |
---|---|---|---|
containerRef |
ref |
✔ | Ref to the DOM element containing your PDF page canvas |
isCropping |
bool |
✔ | Should the cropping overlay be active? (controlled from your app) |
setIsCropping |
func |
✔ | Function to close/hide cropping overlay (used by cancel, after crop, etc.) |
currentPage |
number |
✔ | The current page number (1-based, not zero-indexed) |
onCrop |
func |
Callback called with the cropped image dataURL ((dataUrl) => {})
|
|
getHandlers |
func |
Callback giving you crop/cancel handlers (({ handleSaveClick, stopCropping }) => {} ) |
|
watermarkImage |
string |
(Optional) URL/data URL for watermark logo/image | |
watermarkProps |
object |
(Optional) { opacity, tileWidth, tileHeight } for watermark tiling |
|
showDefaultButtons |
bool |
Show built-in crop/cancel buttons in cropbox? (default: true ) |
-
<CropPreviewButton onClick={...} />
— Use in your own UI to trigger crop/preview. -
<CancelCropButton onClick={...} />
— Use in your own UI to cancel cropping.
-
handleDownload(imageDataUrl, filename = "cropped-image.png")
— Instantly download the cropped image.
-
External UI:
Pass
showDefaultButtons={false}
to hide the cropbox’s own buttons and use the exported buttons in your layout. -
Watermark:
Add
watermarkImage="/logo.png"
and tweakwatermarkProps
as needed. -
Styling:
Tweak cropbox and buttons in your own CSS or fork to change cropbox design.
A full-featured example React app is included in the example/ folder of this repo.
-
Open it, run
npm install
, thennpm run dev
. -
Try cropping, previewing, downloading, and watermarking on any PDF (don't forget to install the package first).
There is an example video in the public
folder for your reference as well.
Q: Does this support touch/mobile?
A: Yes! All drag, resize, and crop actions are available via mouse and touch.
Q: Do I need to use react-pdf-viewer
?
A: No! Any PDF viewer that renders to a canvas (from PDF.js) will work, as long as you pass a ref to the container with the canvas.
Q: Is html2canvas used?
A: No. Cropping works directly on the PDF.js-rendered canvas, so it’s much faster and sharper.
Q: Can I style the crop box?
A: Yes—either with your own CSS, or by modifying the CroppingBox component.
Q: Can I use my own crop/cancel buttons?
A: Yes! Just hide the built-in ones and use the exported <CropPreviewButton />
and <CancelCropButton />
, passing the handlers from getHandlers
.
Q: How do I add a watermark?
A: Pass a watermark image and optionally watermarkProps (opacity, tiling, etc).
PRs and issues are very welcome!
-
Fork this repo
-
Add features or fixes in a branch
-
Add/adjust an example in example/ if needed
-
PRs should be clear and well-commented.
Made by Shivam Kumar >_<
MIT — Free for personal, commercial, and open-source use.
Questions?
Open an issue or ping me on GitHub.
Enjoy cropping PDFs with React! 🎉