v2.0.0

<bmx-signature-pad>

A signature, drawn with a pen, a mouse or a finger, that goes into a form like any other field. The line thins as the pen speeds up and follows the pressure of a real pen, so it looks like ink rather than a trail of dots.

19 properties · 2 events · 13 methods · 6 parts

Example

Nothing is sent anywhere: the form's value is shown here instead.

Stored as strokes, drawn back

With format="json" the value is the strokes themselves; setting it draws them again. This one is read-only.

Show markup
<form id="ex-sig-form">
  <bmx-signature-pad id="ex-sig" name="signature" label="Signature" description="Sign with a mouse, a finger or a pen, or choose Type to type your name." required></bmx-signature-pad>
  <div class="row" style="gap: 8px; margin-top: 12px; flex-wrap: wrap">
    <button type="submit">Send</button>
    <button type="reset">Reset</button>
    <button type="button" id="ex-sig-png">Save PNG</button>
    <button type="button" id="ex-sig-svg">Save SVG</button>
  </div>
</form>
<p class="note" id="ex-sig-out" role="status">Nothing is sent anywhere: the form's value is shown here instead.</p>
<p><img id="ex-sig-img" alt="" style="max-width: 100%; max-height: 90px; display: none" /></p>

<h3>Stored as strokes, drawn back</h3>

<p class="note">With <code>format="json"</code> the value is the strokes themselves; setting it draws them again. This one is read-only.</p>
<bmx-signature-pad id="ex-sig-ro" label="Signed by the account holder" readonly format="json" allow-typing="false" style="--bmx-signature-pad-height: 8rem"></bmx-signature-pad>

<script type="module">
  await customElements.whenDefined('bmx-signature-pad');
  const pad = document.getElementById('ex-sig');
  const out = document.getElementById('ex-sig-out');
  const img = document.getElementById('ex-sig-img');
  document.getElementById('ex-sig-form').addEventListener('submit', e => {
    e.preventDefault();
    const value = new FormData(e.target).get('signature');
    out.textContent = `The form would send a ${value.length.toLocaleString()}-character PNG data URL.`;
    img.src = value;
    img.style.display = 'block';
  });
  pad.addEventListener('bmxChange', e => (out.textContent = e.detail.empty ? 'Empty.' : `Signed (${e.detail.mode === 'type' ? 'typed' : 'drawn'}).`));
  document.getElementById('ex-sig-png').addEventListener('click', () => pad.download('png'));
  document.getElementById('ex-sig-svg').addEventListener('click', () => pad.download('svg'));

  // A signature drawn by a script: three loops and a long tail, as stored strokes.
  const strokes = [];
  const loops = [];
  for (let i = 0; i <= 120; i += 1) {
    const t = i * 0.16;
    loops.push([70 + i * 1.7 + Math.sin(t) * 26, 70 - Math.cos(t) * 30 + (i < 10 ? 10 - i : 0), 0, i * 7]);
  }
  strokes.push(loops);
  const tail = [];
  for (let i = 0; i <= 50; i += 1) tail.push([285 + i * 5, 92 - Math.sin(i / 6) * 16 - i * 0.5, 0, 1000 + i * (i < 25 ? 10 : 4)]);
  strokes.push(tail);
  strokes.push([[180, 40, 0, 1600], [184, 38, 0, 1612]]);
  document.getElementById('ex-sig-ro').value = JSON.stringify({ width: 560, height: 128, strokes });
</script>

WHERE THE SIGNATURE GOES

Nowhere but the form. The value is a PNG data URL by default (format="svg" for a vector, format="json" for the strokes themselves, which can be put back with fromJSON or by setting value). Nothing is sent anywhere by this element.

WHY THE PAPER STAYS LIGHT

The pad is paper-coloured with dark ink in every theme, so the saved image prints and pastes into a document the way it looked when it was signed. --bmx-signature-pad-background and --bmx-signature-pad-ink change both.

ACCESSIBILITY

Drawing needs a pointer, so the pad offers typing as an equal alternative: Type shows a text field, and the name is set in a handwriting font and becomes the signature. The pad itself is an image whose name says whether it is signed; undo, redo and clear are ordinary buttons, and what they did is announced.

Properties

PropertyAttributeTypeDefaultDescription
allowTyping allow-typing boolean true Offer typing a name as well as drawing.
description description string —
disabled disabled boolean false
errorText error-text string — An error supplied by the page.
fileName file-name string 'signature' The file name download offers.
format format BmxSignatureFormat 'png' What the value is: png (a data URL), svg (an SVG document) or json (the strokes).
hideLabel hide-label boolean false
label label string —
messages property only BmxFieldMessages — Replacements for the default wording, by reason.
mode mode BmxSignatureMode 'draw' Drawing or typing.
name name string — The field's name in the form.
penWidth pen-width number 3 The widest line, in CSS pixels. Fast strokes thin to about a third of it.
readonly readonly boolean false Show the signature without letting it change.
required required boolean false A signature is needed before the form can be sent.
scale scale number 2 How many times the screen size saved images are.
strings strings Partial<BmxSignaturePadStrings> | string — Replacements for any of the pad's own wording (an object, or its JSON).
trim trim boolean true Crop saved images to the ink, with a little room around it.
validateOn validate-on BmxValidateOn 'submit' When a missing signature is pointed out.
value value string '' The signature, in format. Setting it to JSON strokes draws them; an empty string clears the pad.

Events

EventDetailDescription
bmxChange BmxSignatureChangeDetail Fired when the signature changes: a stroke ends, the pad is cleared, a change is undone, or the typed name changes.
bmxValidityChange BmxSignatureValidityDetail Fired whenever the resolved validity changes.

Methods

MethodSignatureDescription
checkValidity checkValidity() => Promise<boolean> Validate now and return whether the field passed, without revealing it.
clear clear() => Promise<void> Wipe the pad (or the typed name, in Type mode). Drawn strokes can be brought back with undo.
download download(format?: "png" | "svg", name?: string) => Promise<void> Offers the signature to the reader as a file.
fromJSON fromJSON(data: BmxSignatureData | string) => Promise<void> Draws saved strokes. Accepts the object from toJSON or its JSON text.
isEmpty isEmpty() => Promise<boolean> Whether nothing has been drawn or typed.
redo redo() => Promise<void> Put back what undo took.
reportValidity reportValidity() => Promise<boolean> Validate, reveal any problem, and focus the field if it has one.
setFocus setFocus(options?: FocusOptions) => Promise<void> Focus the first control: the typed name in Type mode, else the first tool.
toDataURL toDataURL(type?: "image/png" | "image/jpeg", scale?: number) => Promise<string> The signature as a data URL: PNG with a see-through ground, or JPEG on the paper colour. Empty string when empty.
toJSON toJSON() => Promise<BmxSignatureData> The strokes (or the typed name), to store and give back to fromJSON later.
toPng toPng(scale?: number) => Promise<Blob | null> The signature as a PNG, scale times its size on screen. Null when empty.
toSvg toSvg() => Promise<string | null> The signature as an SVG document, trimmed to the ink when trim is on. Null when empty.
undo undo() => Promise<void> Take back the last stroke (or the last clear).

Slots

SlotDescription
description Rich help text, in place of the description property.
label Rich label content, in place of the label property.

CSS shadow parts

PartDescription
description The help text.
error The error message.
input The text field in Type mode.
label The label.
pad The paper.
toolbar The buttons.

CSS custom properties

PropertyDescription
--bmx-signature-pad-background The paper. Default white, in every theme.
--bmx-signature-pad-font The handwriting fonts a typed name is shown in.
--bmx-signature-pad-height The height of the paper. Default 11rem.
--bmx-signature-pad-ink The ink colour. Default a blue-black, in every theme.
--bmx-signature-pad-label-font-size The label's font size.
--bmx-signature-pad-line The signing line and its cross.
--bmx-signature-pad-support-font-size Font size of the description and error.