react-signature-canvas and react-signature-pad are both React wrappers designed to capture handwritten signatures within web applications. They abstract the complexity of handling HTML5 Canvas events, touch interactions, and stroke rendering into reusable components. While they share the same core goal, they differ significantly in their underlying dependencies, API design patterns, and maintenance status. react-signature-canvas is a modern, lightweight wrapper around signature_pad that embraces React hooks and functional components. In contrast, react-signature-pad is an older library that often relies on class-based patterns or outdated wrapper logic, leading to potential compatibility issues with modern React versions.
Capturing a user's signature in a browser requires more than just drawing on a <canvas> element. You need to handle high-DPI screens, touch events on mobile devices, variable stroke smoothing, and data export formats. Two packages often appear in this space: react-signature-canvas and react-signature-pad. While they sound similar, their engineering reality is vastly different.
The most critical factor in choosing between these two is their relationship with the underlying engine and their maintenance lifecycle.
react-signature-canvas acts as a thin, modern React wrapper around the industry-standard signature_pad library. It is designed to work seamlessly with functional components and React Hooks. The maintainers actively update it to match new releases of signature_pad, ensuring that performance optimizations and security patches flow directly to your application.
// react-signature-canvas: Modern functional usage
import SignatureCanvas from 'react-signature-canvas';
function SignatureForm() {
const sigCanvas = useRef({});
const clearSignature = () => {
sigCanvas.current.clear();
};
return (
<div>
<SignatureCanvas
ref={sigCanvas}
canvasProps={{ className: 'sigCanvas' }}
/>
<button onClick={clearSignature}>Clear</button>
</div>
);
}
react-signature-pad, conversely, represents an older generation of React wrappers. Many versions of this package were built during the era of class components and have not been consistently updated to reflect changes in React's rendering engine or the underlying canvas logic. In many cases, the npm package points to abandoned repositories or forks that lag years behind the core signature_pad project.
// react-signature-pad: Often requires class components or legacy patterns
// Note: API may vary significantly by fork/version
import SignaturePad from 'react-signature-pad';
class LegacySignature extends React.Component {
render() {
return (
<SignaturePad
canvasProps={{ width: 400, height: 200 }}
// Some versions lack proper ref forwarding for imperative calls
/>
);
}
}
The way you interact with the canvas instance differs sharply between the two, impacting how easily you can implement features like "Clear," "Undo," or "Save."
react-signature-canvas leverages React refs to expose the underlying signature_pad instance methods directly. This pattern feels natural to React developers and allows for imperative control when needed (like clearing the canvas) without breaking the declarative flow.
// react-signature-canvas: Direct method access via ref
const handleSave = () => {
if (sigCanvas.current.isEmpty()) {
alert('Please sign first');
} else {
// Returns a dataURL string
const dataURL = sigCanvas.current.toDataURL();
submitToServer(dataURL);
}
};
react-signature-pad often wraps these methods in its own abstraction layer or, in worse cases, fails to expose them cleanly. This can force developers to dig into the component's internal state or use awkward workarounds to access the raw canvas context.
// react-signature-pad: Access can be inconsistent
const handleSaveLegacy = (componentInstance) => {
// Depending on the version, you might access .signature_pad directly
// or rely on callback props which complicates state management
const canvas = componentInstance.signature_pad;
if (canvas) {
const data = canvas.toDataURL();
}
};
Handling input events correctly is the hardest part of signature pads. You need to support mouse, touch, and pointer events uniformly to ensure the signature looks the same on an iPad as it does on a desktop.
react-signature-canvas passes event handling duties directly to the robust signature_pad engine. It correctly scales the canvas based on the device pixel ratio (DPR). This prevents signatures from looking blurry on Retina displays or mobile screensβa common pitfall in custom canvas implementations.
// react-signature-canvas: Automatic DPR handling
<SignatureCanvas
ref={sigCanvas}
canvasProps={{
width: 500,
height: 200,
className: 'sigCanvas'
}}
// Props are passed directly to the underlying instance
penColor='rgb(0, 0, 0)'
/>
react-signature-pad frequently struggles with DPR scaling in older versions. Developers often report that signatures appear tiny on high-resolution screens or that touch events lag because the wrapper does not efficiently delegate pointer events to the underlying engine.
// react-signature-pad: May require manual scaling props
<SignaturePad
width={500}
height={200}
// Often lacks automatic window resize listeners
// leading to distorted strokes on orientation change
/>
Ultimately, you need to send the signature to your backend. Both libraries aim to provide data URLs (base64 images) or raw point data, but the reliability varies.
react-signature-canvas provides consistent access to toDataURL() and toData(). The toData() method returns an array of points, allowing you to re-render the signature vectorially later if needed, which is superior to saving a static bitmap.
// react-signature-canvas: Vector data export
const getVectorData = () => {
// Returns array of points: [{x, y, pressure}, ...]
const points = sigCanvas.current.toData();
return JSON.stringify(points);
};
react-signature-pad may expose similar methods, but due to version fragmentation, the return types or method names can differ. Relying on this for critical legal documents introduces risk if the library behaves differently across environments.
// react-signature-pad: Inconsistent API surface
// Some forks rename methods or return wrapped objects
const getVectorDataLegacy = (instance) => {
return instance.getData(); // Method name might vary
};
When implementing signatures, developers often face specific challenges. Here is how the two libraries handle them:
react-signature-canvas recommends (and supports) manually clearing and resizing the canvas on window resize events using the ref. react-signature-pad often lacks clear documentation on handling this, leading to distorted signatures.react-signature-canvas inherits signature_pad's ability to prevent default touch actions effectively. Older wrappers sometimes fail to bind these listeners correctly.react-signature-canvas includes robust TypeScript definitions, making it safe for typed projects. react-signature-pad often requires manual type declarations or @ts-ignore comments.| Feature | react-signature-canvas | react-signature-pad |
|---|---|---|
| Maintenance | β Active & Reliable | β Stagnant / Deprecated |
| React Pattern | β Hooks & Functional | β οΈ Class / Legacy |
| High-DPI Support | β Automatic Scaling | β οΈ Often Manual/Buggy |
| Ref Access | β Direct Instance Methods | β οΈ Wrapped / Inconsistent |
| TypeScript | β Built-in Types | β Community Types Only |
| Underlying Engine | β
Latest signature_pad | β οΈ Outdated Forks |
For professional frontend development, the choice is clear. react-signature-canvas is the only viable option for modern applications. It reduces technical debt, ensures compatibility with current React versions, and leverages the battle-tested signature_pad engine correctly.
react-signature-pad should be treated as a legacy artifact. If you encounter it in an existing codebase, plan to migrate away from it. Its lack of active maintenance means that as browsers update their canvas or touch event implementations, this library is likely to break without warning.
Implementation Tip: Whichever library you use, always ensure you handle the window.resize event to reset the canvas dimensions, or your users' signatures will look stretched after rotating their mobile devices. With react-signature-canvas, this is a straightforward ref call:
useEffect(() => {
const resizeCanvas = () => {n const ratio = Math.max(window.devicePixelRatio || 1, 1);
sigCanvas.current.canvas.width = sigCanvas.current.canvas.offsetWidth * ratio;
sigCanvas.current.canvas.height = sigCanvas.current.canvas.offsetHeight * ratio;
sigCanvas.current.context.scale(ratio, ratio);
};
window.addEventListener("resize", resizeCanvas);
return () => window.removeEventListener("resize", resizeCanvas);
}, []);
Choose react-signature-canvas for any new production project. It is actively maintained, fully compatible with modern React (including hooks and functional components), and provides a clean, typed API. Its direct dependency on the latest signature_pad ensures you get recent bug fixes and performance improvements without needing to manage the underlying canvas logic yourself.
Avoid react-signature-pad for new development. This package is largely considered deprecated or stagnant, with many versions failing to keep pace with React's evolution (such as the shift to hooks) and updates to the underlying signature_pad library. Using it introduces unnecessary risk of breaking changes, security vulnerabilities, and difficulty finding community support for bugs.
A React wrapper component around signature_pad.
Originally, this was just an unopinionated fork of react-signature-pad that did not impose any styling or wrap any other unwanted elements around your canvas -- it's just a wrapper around a single canvas element!
Hence the naming difference.
Nowadays, this repo / library has significantly evolved, introducing new features, fixing various bugs, and now wrapping the upstream signature_pad to have its updates and bugfixes baked in.
This fork also allows you to directly pass props to the underlying canvas element, has new, documented API methods you can use, has new, documented props you can pass to it, has a live demo, has a CodeSandbox playground, has 100% test coverage, and is written in TypeScript.
npm i -S react-signature-canvas
import React from 'react'
import { createRoot } from 'react-dom/client'
import SignatureCanvas from 'react-signature-canvas'
createRoot(
document.getElementById('my-react-container')
).render(
<SignatureCanvas penColor='green'
canvasProps={{width: 500, height: 200, className: 'sigCanvas'}} />,
)
The props of SignatureCanvas mainly control the properties of the pen stroke used in drawing. All props are optional.
velocityFilterWeight : number, default: 0.7minWidth : number, default: 0.5maxWidth : number, default: 2.5minDistance: number, default: 5dotSize : number or function,
default: () => (this.minWidth + this.maxWidth) / 2penColor : string, default: 'black'throttle: number, default: 16There are also two callbacks that will be called when a stroke ends and one begins, respectively.
onEnd : functiononBegin : functionAdditional props are used to control the canvas element.
canvasProps: object
<canvas /> elementbackgroundColor : string, default: 'rgba(0,0,0,0)'
clear convenience method (which itself is called internally during resizes)clearOnResize: bool, default: true
Of these props, all, except for canvasProps and clearOnResize, are passed through to signature_pad as its options.
signature_pad's internal state is automatically kept in sync with prop updates for you (via a componentDidUpdate hook).
All API methods require a ref to the SignatureCanvas in order to use and are instance methods of the ref.
import React, { useRef } from 'react'
import SignatureCanvas from 'react-signature-canvas'
function MyApp() {
const sigCanvas = useRef(null);
return <SignatureCanvas ref={sigCanvas} />
}
isEmpty() : boolean, self-explanatoryclear() : void, clears the canvas using the backgroundColor propfromDataURL(base64String, options) : void, writes a base64 image to canvastoDataURL(mimetype, encoderOptions): base64string, returns the signature image as a data URLfromData(pointGroupArray): void, draws signature image from an array of point groupstoData(): pointGroupArray, returns signature image as an array of point groupsoff(): void, unbinds all event handlerson(): void, rebinds all event handlersgetCanvas(): canvas, returns the underlying canvas ref.
Allows you to modify the canvas however you want or call methods such as toDataURL()getTrimmedCanvas(): canvas, creates a copy of the canvas and returns a trimmed version of it, with all whitespace removed.getSignaturePad(): SignaturePad, returns the underlying SignaturePad reference.The API methods are mostly just wrappers around signature_pad's API.
on() and off() will, in addition, bind/unbind the window resize event handler.
getCanvas(), getTrimmedCanvas(), and getSignaturePad() are new.
You can interact with the example in a few different ways:
Run npm start and navigate to http://localhost:1234/.
Hosted locally via the example/ directory
View the live demo here.
Hosted via the gh-pages branch, a standalone version of the code in example/
Play with the CodeSandbox here.
Hosted via the codesandbox-example branch, a slightly modified version of the above.