webdevpuneet.com

Fabric.js Signature Pad — Free-Drawing Canvas Export Snippet

Fabric.js Signature Pad · Forms · Plain HTML, CSS & JS · Live preview

CategoryForms

Copy & paste

Source Code

Requires
<div class="fsp-stage">
  <div class="fsp-head">
    <span class="fsp-tag">Fabric.js · free drawing</span>
    <h2>Signature Pad</h2>
    <p>Sign below with mouse or touch. Adjust pen width and color, then export your signature as a PNG.</p>
  </div>
  <div class="fsp-pad">
    <canvas id="fspCanvas"></canvas>
    <div class="fsp-baseline"></div>
  </div>
  <div class="fsp-controls">
    <label class="fsp-field">
      <span>Pen width</span>
      <input type="range" id="fspWidth" min="1" max="10" value="3" />
    </label>
    <div class="fsp-colors" id="fspColors">
      <button class="fsp-swatch is-on" data-color="#1a1a2e" style="background:#1a1a2e"></button>
      <button class="fsp-swatch" data-color="#1e40af" style="background:#1e40af"></button>
      <button class="fsp-swatch" data-color="#7c2d12" style="background:#7c2d12"></button>
    </div>
    <div class="fsp-actions">
      <button class="fsp-btn fsp-btn-ghost" id="fspClear">Clear</button>
      <button class="fsp-btn" id="fspExport">Export as PNG</button>
    </div>
  </div>
  <img id="fspPreview" class="fsp-preview" alt="Exported signature preview" hidden />
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Free-drawing mode
isDrawingMode: true turns pointer input into smoothed Path strokes automatically.
Configurable PencilBrush
Width and color are live properties read fresh on every new stroke.
Multi-color signing
Swatch buttons swap freeDrawingBrush.color without affecting past strokes.
High-resolution export
toDataURL multiplier: 2 rasterizes at double the on-screen resolution.
Clean clear behavior
clear() plus an explicit backgroundColor reset keeps the paper tone.
Guide baseline
A dashed CSS line hints where to sign without being part of the canvas.
Touch-ready by default
Fabric\u2019s pointer handling works with mouse, pen, and touch input alike.
Real exportable image
The export button produces an actual PNG data URL, previewed inline.

About this UI Snippet

Fabric.js Signature Pad — Free Drawing and Canvas Export Explained

Screenshot of the Fabric.js Signature Pad snippet rendered live

Capturing a signature looks simple — draw on a canvas, save the pixels — but doing it well means smooth freehand strokes, adjustable pen properties, and a reliable way to get the result back out as an image. Fabric.js's drawing mode and toDataURL() handle all three without any manual pointer-event math.

Turning a Fabric canvas into a drawing surface

Setting isDrawingMode: true on a fabric.Canvas switches it from an object-selection surface to a freehand drawing surface: pointer-down starts a stroke, pointer-move extends it, and pointer-up commits it as a fabric.Path object. Fabric handles the pointer-to-path conversion internally, smoothing the raw input points into a single SVG-style path rather than leaving you with a polyline of straight segments.

Configuring the brush

canvas.freeDrawingBrush holds the active brush instance. This snippet explicitly assigns new fabric.PencilBrush(canvas) — Fabric's default freehand brush, which produces a single continuous stroke with a flat width — rather than relying on whatever the canvas defaulted to, so that width and color are guaranteed configurable properties on a known object:

canvas.freeDrawingBrush.width = 3; canvas.freeDrawingBrush.color = '#1a1a2e';

Both properties are read fresh by the brush on every new stroke, so changing the range slider or clicking a color swatch mid-signature only affects strokes drawn *after* the change — already-committed paths keep their original width and color, which is the correct, expected behavior for a signature pad.

Exporting as PNG

canvas.toDataURL({ format: 'png', quality: 1, multiplier: 2 }) rasterizes the entire canvas — background color plus every drawn path — into a base64-encoded PNG data URL. The multiplier: 2 option is the detail worth calling out: Fabric renders the export at twice the on-screen resolution, internally scaling the canvas up before rasterizing and back down after, so the exported signature stays crisp even if it's later displayed larger than the pad itself (for example, printed on a document). Without a multiplier, the export is pixel-for-pixel identical to the visible canvas size, which can look soft when scaled up.

Clearing without losing the drawing surface

canvas.clear() removes every Path object Fabric has committed, but it also resets backgroundColor to Fabric's own default (transparent), which is why the clear handler explicitly re-sets canvas.backgroundColor afterward — otherwise the pad would turn transparent instead of returning to its paper tone.

Why a canvas-based pad beats raw <canvas> pointer code

Rolling this by hand means listening to pointerdown/pointermove/pointerup, buffering points, and drawing smoothed curves yourself — solvable, but Fabric's PencilBrush already does point-smoothing, and because strokes become real Path objects, you get undo (canvas.remove() on the last path), per-stroke styling, and JSON serialization for free, none of which raw canvas drawing gives you without extra code.

Step by step

How to Use

  1. 1
    Add the Fabric.js CDNInclude fabric.min.js from the CDN panel — it attaches a global fabric object.
  2. 2
    Paste HTML, CSS, and JSA ready-to-sign pad renders with a guide baseline.
  3. 3
    Sign with mouse or touchisDrawingMode routes pointer input straight into smoothed Path strokes.
  4. 4
    Adjust pen width and colorThe slider and swatches update freeDrawingBrush live for new strokes.
  5. 5
    Clear the padcanvas.clear() wipes all strokes; the background color is re-applied after.
  6. 6
    Export as PNGtoDataURL with multiplier: 2 renders a crisp, higher-resolution image preview.

Real-world uses

Common Use Cases

Contract and consent signing
Capture a legal or consent signature with smooth freehand strokes, using Fabric's free-drawing mode and a configurable PencilBrush.
Delivery sign-off pads
Provide a recipient sign-off for a courier app, with colour swatches and a Clear button for another attempt.
Quick sketch capture
Offer a minimal freehand input for annotations, where brush width and colour are read fresh at the start of every new stroke.
Canvas export learning
Learn how toDataURL with a multiplier of 2 rasterises a high-resolution PNG, doubling the on-screen resolution for crisp output.
Kiosk and tablet check-in
Support touch-friendly signing for in-person visits at a front desk, with multi-colour signing handled by swapping freeDrawingBrush.color only.

Got questions?

Frequently Asked Questions

Fabric does create a default free-drawing brush automatically, but explicitly constructing new fabric.PencilBrush(canvas) guarantees the brush type and gives an unambiguous, documented object to set width and color on, which keeps the code portable across Fabric versions.

No. freeDrawingBrush.width and .color are read when a new stroke begins, and each committed stroke becomes its own fabric.Path object with its own fixed styling, so past strokes are unaffected by later changes to the brush.

multiplier scales the rendered export resolution relative to the canvas\u2019s on-screen size. At 1 (the default) the export is pixel-for-pixel identical to the visible canvas, which can look soft if the image is later displayed larger. multiplier: 2 renders at double resolution for a crisper result.

clear() removes every canvas object AND resets background-related properties to Fabric\u2019s defaults, which is transparent. The clear handler explicitly re-applies the paper background color afterward so the pad does not turn transparent.

Check canvas.getObjects().length after drawing stops \u2014 free drawing commits each stroke as a Path object added to the canvas\u2019s object list, so zero objects means nothing was signed yet.

Yes \u2014 call canvas.toSVG() instead of toDataURL(). Because each stroke is already a Path object, Fabric serializes it as a real SVG <path> with an exact d attribute rather than rasterizing pixels.