Signature
A signature pad lets users sign with a mouse, a pen, or a finger. Use it to confirm an order, accept a contract, or hand over a delivery.
Overview
The signature pad is a canvas element with Tabler styles around it. Drawing is handled by the Signature Pad library.
Use the signature class on the wrapper and signature-canvas on the canvas. The wrapper draws a solid border, and the canvas adds a dashed one, so the signing area is easy to see. The cursor turns into a crosshair over the canvas.
Try it below. Draw with the mouse, or with a finger on a touch screen.
<div class="signature position-relative" style="width: 100%; max-width: 26rem;">
<canvas id="signature-overview" class="signature-canvas" width="400" height="200" style="height: 10rem"></canvas>
</div>Installation
The library is not part of the Tabler bundle. Install it with npm:
npm install signature_pad
Or include it from a CDN:
<script src="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/libs/signature_pad/dist/signature_pad.umd.min.js"></script>
Usage
Markup
Wrap the canvas in a signature element. Set width and height on the canvas, so it has a size before the script runs.
Also set the height in CSS. Tabler styles the canvas with width: 100%, so without a CSS height the canvas keeps the ratio of its attributes. The resize code below then reads a new height on every run, and the pad gets shorter each time.
<div class="signature position-relative">
<canvas id="signature-default" class="signature-canvas" width="400" height="400" style="height: 16rem"></canvas>
</div>Init the pad
Create the pad after the DOM is ready. Set a transparent background, so the canvas follows the card or the page. Take the pen color from the canvas text color, so the signature also works in dark mode.
document.addEventListener('DOMContentLoaded', function () {
const canvas = document.getElementById('signature-default')
const signaturePad = new SignaturePad(canvas, {
backgroundColor: 'transparent',
penColor: getComputedStyle(canvas).color,
})
})
Keep the drawing sharp
A canvas has two sizes: the CSS size and the pixel size. On a retina screen they differ, and the line looks blurry. Scale the canvas to the device pixel ratio, and do it again on resize.
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)
// resizing clears the canvas, so put the drawing back
signaturePad.fromData(signaturePad.toData())
}
window.addEventListener('resize', resizeCanvas)
resizeCanvas()
Clear button
Place a button in the corner of the wrapper and call clear() on it. The wrapper needs position-relative for this.
<div class="signature position-relative" style="width: 100%; max-width: 26rem;">
<div class="position-absolute top-0 end-0 p-2">
<button type="button" class="btn btn-icon" id="signature-clear-button" title="Clear signature">
<!-- Download SVG icon from http://tabler.io/icons/icon/trash -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M4 7l16 0" />
<path d="M10 11l0 6" />
<path d="M14 11l0 6" />
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
</svg>
</button>
</div>
<canvas id="signature-clear" class="signature-canvas" width="400" height="200" style="height: 10rem"></canvas>
</div>document.getElementById('signature-clear-button').addEventListener('click', function () {
signaturePad.clear()
})
Pen color
Change penColor at any time. New strokes use the new color, and the old ones keep theirs.
document.getElementById('pen-color').addEventListener('input', function (event) {
signaturePad.penColor = event.target.value
})
Save the signature
Use toDataURL() to read the drawing. Without arguments you get a PNG. Pass image/svg+xml for a vector file. Check isEmpty() first, so you do not save a blank pad.
if (signaturePad.isEmpty()) {
// ask the user to sign first
} else {
const png = signaturePad.toDataURL()
const svg = signaturePad.toDataURL('image/svg+xml')
}
Use fromDataURL() to show a signature you saved earlier.
Pad inside a modal
A canvas has no size while the modal is hidden, so the pad must start after the modal opens. Listen for the Bootstrap shown.bs.modal event instead of DOMContentLoaded.
document.getElementById('modal-signature').addEventListener('shown.bs.modal', function () {
// create the pad here
})
Examples
Signature in a form
Put the pad in a form group with a label, the same as any other field. Add the legal text under it when the signature is binding.
Confirm transfer
<div class="card">
<div class="card-body">
<h3 class="card-title">Confirm transfer</h3>
<div class="mb-3">
<label class="form-label required">Signature</label>
<div class="signature position-relative">
<div class="position-absolute top-0 end-0 p-2">
<button type="button" class="btn btn-icon" id="signature-form-clear" title="Clear signature">
<!-- Download SVG icon from http://tabler.io/icons/icon/trash -->
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
<path d="M4 7l16 0" />
<path d="M10 11l0 6" />
<path d="M14 11l0 6" />
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
</svg>
</button>
</div>
<canvas id="signature-form" class="signature-canvas" width="400" height="180" style="height: 9rem"></canvas>
</div>
</div>
<div class="text-secondary fs-5"> I agree that this signature is the electronic representation of my signature for all purposes when I use it on documents. </div>
<div class="mt-4 d-flex">
<button type="button" class="btn">Cancel</button>
<button type="button" class="btn btn-primary ms-auto">Confirm transfer</button>
</div>
</div>
</div>Accessibility
- A canvas cannot be used with a keyboard. Offer a second way to sign, for example a text field where the user types their full name.
- Give the pad a real
<label>, so users know what they sign. Link it to the field withforandid. - Use a
<button type="button">for the clear action. Adivwith button classes is not reachable with the keyboard. - Tell users what happens with the drawing. A signature is personal data, so say where you store it and for how long.
- Do not rely on the dashed border alone. Add a short hint, for example
Sign inside the box.
