signature_pad: variable-width Bézier strokes on an HTML5 canvas, and the resize trap that wipes them
HTML5 canvas based smooth signature drawing
At a glance
- What is it?
- signature_pad is a dependency-free TypeScript library that turns pointer movement on a canvas into smooth, velocity-shaped ink. This analysis covers its smoothing options, its export formats, the canvas resize problem, and what it leaves to you.
- Who is it for?
- Use signature_pad when you need a signature capture widget inside a web page and can handle canvas sizing and storage yourself. Do not expect it to act as a hardware pad driver or a document signing product.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- szimek/signature_pad12,077 ★ · +33
| Repository | 2026-09-22 | 2026-11-14 |
|---|---|---|
| szimek/signature_pad | 12k | 12.1k |
33 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Stroke width comes from velocity, so the pen options are about speed
signature_pad draws with variable width Bézier curve interpolation, an approach it credits to the Smoother Signatures post from Square. The visible effect is that a line is thinner where the pointer moves fast and thicker where it slows down, instead of a constant-width polyline.
The options that shape this are small in number. minWidth is the minimum width of a line and defaults to 0.5. maxWidth is the maximum and defaults to 2.5. dotSize is the radius of a single dot and also the width at the start of a mark, and it can be a float or a function. velocityFilterWeight is the weight used to modify the new velocity based on the previous velocity, defaulting to 0.7.
In practice that means the default signature is a thin line, only 0.5 to 2.5 units wide. If your canvas is scaled for high DPI screens or displayed large, the defaults may look faint, and the README's own example raises minWidth to 5 and maxWidth to 10 for a bolder pen.
throttle and minDistance decide how many points the curve is fitted to
Two options limit how often a new point enters the stroke. throttle draws the next point at most once per x milliseconds, defaults to 16, and can be set to 0 to turn throttling off. minDistance adds the next point only if the previous one is farther than x pixels away, and defaults to 5.
The two work against each other in a useful way. Lowering both gives the Bézier fit more points and a more faithful path, at the price of more work per pointer event. Raising them gives you fewer points and a coarser line. Because a velocity based width is computed between points, thinning the points also changes how thick the stroke appears.
The options are readable and writable at runtime as properties, for example signaturePad.minWidth = 5, so a settings panel in your page can change the pen without recreating the object.
A transparent background makes JPEG exports come out wrong
backgroundColor is the color used to clear the canvas and defaults to rgba(0,0,0,0), transparent black. penColor defaults to black. Both accept any format that context.fillStyle accepts.
The transparent default has a direct consequence for export. The README says to use a non-transparent color such as rgb(255,255,255) if you want to save signatures as JPEG images, because JPEG has no alpha channel. If you leave the default and export JPEG, the transparent area has nothing sensible to turn into.
Export itself is a short list of calls on the instance. toDataURL() returns a PNG data URL, toDataURL("image/jpeg") returns JPEG, toDataURL("image/jpeg", 0.5) sets the JPEG quality to 0.5, and toDataURL("image/svg+xml") returns an SVG data URL. toSVG() returns the SVG as a plain string without base64 conversion. SVG output keeps the strokes as vector paths, while the others are raster snapshots of the canvas.
Resizing the canvas silently erases the signature
This is the main trap in the library, and the README spells it out. When you change the width or height of a canvas, the browser clears it automatically, and SignaturePad does not know it happened. You can call signaturePad.redraw() to reset the drawing, or signaturePad.clear() to make sure isEmpty() returns the right value.
On mobile this hurts most, because rotating the screen triggers a resize. The README offers two workarounds: lock the screen orientation, or read an image from the canvas before resizing and write it back afterwards.
For high DPI screens, the canvas has to be scaled by devicePixelRatio. That scaling is also needed to display signatures loaded through SignaturePad#fromDataURL correctly. The README's example does it like this:
function resizeCanvas() {
const ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
signaturePad.clear(); // otherwise isEmpty() might return incorrect value
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();Note the clear() call inside: the sizing code itself is what empties the pad, so a user who has already signed will lose the signature when the window changes.
Four stroke events, and only one of them can be cancelled
Events are registered with the standard addEventListener on the SignaturePad instance. The four are beginStroke, endStroke, beforeUpdateStroke and afterUpdateStroke.
beginStroke fires before a stroke begins and can be canceled with event.preventDefault(). That is the hook for locking the pad, for example after a form is submitted or while a modal is closing. The other three are notifications: endStroke after a stroke ends, and the before and after update pair around each stroke update.
The README example passes the once option as the third argument, so the listener fires a single time:
const signaturePad = new SignaturePad(canvas);
signaturePad.addEventListener("beginStroke", () => {
console.log("Signature started");
}, { once: true });A common use is enabling a Submit button on the first beginStroke. Because the pair of update events fires for every update, handlers attached there run often and should stay cheap.
One package with UMD and ES module builds, and a recent release history
The project says it works in all modern desktop and mobile browsers and does not depend on any external libraries. It ships as UMD and as an ES6 module, and package.json maps import to dist/signature_pad.js and require to dist/signature_pad.umd.js, with type declarations under dist/types.
The two package manager installs are:
npm install --save signature_padyarn add signature_padFor a plain page, a script tag loads the minified UMD build from jsDelivr. Replace [version] with the version you want:
<script src="https://cdn.jsdelivr.net/npm/signature_pad@[version]/dist/signature_pad.umd.min.js"></script>Recent releases are v5.1.2 on 2025-11-16, v5.1.3 on 2025-12-03 and v5.1.4 on 2026-07-31, and the last push to the master branch was on 2026-10-29. The repository uses semantic-release packages for publishing, esbuild for bundling, and the Node test runner for tests, with the command node --import ./tests/setup.ts --test.
It draws and exports, but erase, undo and legal signing are yours to build
signature_pad is a front end drawing component. It is not a document signing service, it does not store signatures, and it does not ship a server. Saving a signature means taking the data URL or SVG string and sending it somewhere, and the README has a tips section for handling data URI encoded images on the server side.
It also does not present itself as a hardware pad driver. It draws on an HTML5 canvas inside your page, so it will not talk to a dedicated signature tablet or fill in a signature line inside a desktop application.
The options and events lists contain no erase or undo entries. The README instead links two separate jsfiddle demos, one for an erase feature and one for an undo feature, which suggests those behaviours are built on top of the library rather than configured through it. Check those fiddles before deciding to build your own, and plan your own handling of canvas sizing, because the library leaves it to the page.
Editorial conclusion
Use signature_pad when you need a signature capture widget inside a web page and can handle canvas sizing and storage yourself. Do not expect it to act as a hardware pad driver or a document signing product. Before shipping, test your resize and orientation handling and decide whether you will save PNG, JPEG, or SVG.
Frequently asked questions
What is a signature pad in the signature_pad library?
signature_pad is a JavaScript library for drawing smooth signatures on an HTML5 canvas. It uses variable width Bézier curve interpolation and has no external library dependencies.
How to use signature_pad in a web page?
Get a canvas element and create new SignaturePad(canvas). Then call toDataURL() to get a PNG data URL, or toSVG() for an SVG string. Options such as minWidth, maxWidth and penColor can be passed to the constructor.
How to install signature_pad?
Run npm install --save signature_pad or yarn add signature_pad. You can also load the UMD build from jsDelivr with a script tag, replacing [version] with the release you want.
Can I use signature_pad on a phone?
The project says it works in all modern desktop and mobile browsers. On mobile, rotating the screen resizes the canvas and the browser clears it, so handle orientation changes.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/szimek-signature-pad)Star history chart for your README
[](https://hysenlabs.com/projects/szimek-signature-pad)Was this useful?