# Signature pads with no way to type a signature

Source: https://easeweb.dev/learn/signature-pads
Topics: Keyboard and focus > Everything works with a keyboard, with no exceptions (WCAG 2.1.3)
The fix: Either add a labelled text field beside the pad, "Type your full name to sign", and accept the form with either one; or replace the pad with that field. Drawing can stay as an extra, never as the only way to sign.
Test with: keyboard, screen reader, speech input
References: https://www.w3.org/WAI/WCAG22/Understanding/keyboard-no-exception.html https://www.w3.org/WAI/WCAG22/Understanding/keyboard.html https://www.w3.org/WAI/WCAG22/Understanding/pointer-gestures.html https://github.com/szimek/signature_pad https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

## What happens

A bike rental shop asks each customer to sign its rental agreement online before they collect the bike. The form has a Full name field, then a Signature box with a pen line and a Clear button, then "Sign and send". The box is a signature pad, a canvas that draws a line wherever the mouse, a finger or a stylus moves while it is pressed. It feels like signing on paper, which is why the shop chose it.

A keyboard user fills in the name, presses Tab, and lands on Clear: the pad was skipped. Nothing they can press draws in it. They press "Sign and send" and get "Please sign in the box." The agreement can't be signed, so the bike can't be rented.

## Why it fails

WCAG 2.1.3, Level AAA, asks for everything to work from a keyboard, with no exceptions. 2.1.1, the Level A version, allows one: a function whose underlying job needs a path traced by the pointer, not only where it starts and ends, such as freehand drawing. A drawn signature may be one. The W3C's notes on pointer gestures say that "entering your signature may be inherently path-based (although acknowledging something or confirming your identity need not be)."

So the pad may rely on the exception 2.1.1 allows, but at Level AAA there is no exception to use. The way to pass is not to make the pad drawable by keyboard, but to give the function, signing the agreement, a way that needs no path at all: typing a name.

The browser has nothing to offer here. A canvas is a bitmap: it has no role, takes no focus and reads no keys unless the author adds them, and signature pad libraries such as signature_pad listen for pointer, mouse and touch events only. The hidden field that carries the signature is filled from the drawing, so nothing else can fill it.

## Who is affected

Signing usually comes at the end of a flow: a rental, a delivery, a consent form, a lease. Someone who has filled in every field with a keyboard, a switch or their voice reaches the last step and can't finish. On a phone with a screen reader on, a touch goes to the screen reader first, so drawing takes a pass-through gesture, in a box the person can't see.

## What automation and AI miss

axe and similar scanners see a canvas with no role, which is not a control, and a Clear button with a name, and report nothing. They don't try to sign, so they don't learn that the form can't be sent without drawing. AI tools asked for a signature field may reach for a canvas library and add nothing else, as the examples of libraries such as signature_pad show a pad alone. The EaseWeb audit sends a review lead for each canvas or SVG at least 120 by 60 pixels that listens for pointerdown or mousedown, takes no focus, and has no text field in its fieldset, or failing that its parent, so a person can check whether what it draws can be typed.

## Before: a drawing pad and nothing else

```html
<form class="agreement">
  <p class="field">
    <label for="name">Full name</label>
    <input id="name" name="name" autocomplete="name" required>
  </p>
  <div class="signature">
    <p>Signature</p>
    <canvas id="pad" width="400" height="140"></canvas>
    <button type="button" id="clear">Clear</button>
    <input type="hidden" name="signature" id="signature-data">
    <p id="signature-error" class="error" hidden>Please sign in the box.</p>
  </div>
  <button type="submit">Sign and send</button>
</form>
```

```js
import SignaturePad from 'signature_pad';

const form = document.querySelector('.agreement');
const pad = new SignaturePad(document.getElementById('pad'));
const error = document.getElementById('signature-error');

document.getElementById('clear').addEventListener('click', () => pad.clear());

form.addEventListener('submit', (event) => {
  if (pad.isEmpty()) {
    event.preventDefault();
    error.hidden = false;
    return;
  }
  document.getElementById('signature-data').value = pad.toDataURL();
});
```

The name field and the buttons are fine. The signature is where it fails:

- Tab moves from Full name to Clear: the pad is never a stop, and no key draws in it.
- The hidden field is filled only from the drawing, so there is no other way to sign.
- "Sign and send" refuses the form until something is drawn, so a keyboard user can't send it at all.

## After: type or draw

```html
<form class="agreement">
  <p class="field">
    <label for="name">Full name</label>
    <input id="name" name="name" autocomplete="name" required>
  </p>
  <fieldset class="signature">
    <legend>Signature</legend>
    <label for="typed-signature">Type your full name to sign</label>
    <input id="typed-signature" name="typed-signature" autocomplete="name">
    <p>Or draw your signature</p>
    <canvas id="pad" width="400" height="140"></canvas>
    <button type="button" id="clear">Clear drawing</button>
    <input type="hidden" name="signature" id="signature-data">
    <p id="signature-error" class="error" hidden>Type your name or draw your signature.</p>
  </fieldset>
  <button type="submit">Sign and send</button>
</form>
```

```js
import SignaturePad from 'signature_pad';

const form = document.querySelector('.agreement');
const pad = new SignaturePad(document.getElementById('pad'));
const typed = document.getElementById('typed-signature');
const error = document.getElementById('signature-error');

document.getElementById('clear').addEventListener('click', () => pad.clear());

form.addEventListener('submit', (event) => {
  if (pad.isEmpty() && !typed.value.trim()) {
    event.preventDefault();
    error.hidden = false;
    typed.focus();
    return;
  }
  if (!pad.isEmpty()) {
    document.getElementById('signature-data').value = pad.toDataURL();
  }
});
```

1. Group the signature in a `fieldset` with the legend "Signature", so both ways to sign are read as one question.
2. Put a labelled text field first, "Type your full name to sign". Tab reaches it, a screen reader reads its label, and voice control can dictate into it.
3. Keep the pad after it, under "Or draw your signature", for people who like to draw.
4. Accept the form when either one is filled in, and only read the drawing when there is one.
5. If neither is filled in, say both ways in the error and move focus to the typed field.

This fixes the Before and passes 2.1.3: signing no longer needs a path, because a typed name does the same job. The drawing stays as a shortcut for people who want it.

## After: a typed name only

```html
<form class="agreement">
  <p class="field">
    <label for="name">Full name</label>
    <input id="name" name="name" autocomplete="name" required>
  </p>
  <div class="signature">
    <label for="typed-signature">Type your full name to sign</label>
    <input id="typed-signature" name="signature" autocomplete="name">
    <p id="signature-error" class="error" hidden>Type your name to sign.</p>
  </div>
  <button type="submit">Sign and send</button>
</form>
```

```js
const form = document.querySelector('.agreement');
const typed = document.getElementById('typed-signature');
const error = document.getElementById('signature-error');

form.addEventListener('submit', (event) => {
  if (!typed.value.trim()) {
    event.preventDefault();
    error.hidden = false;
    typed.focus();
  }
});
```

1. Replace the pad, its Clear button and the hidden field with one labelled text field, "Type your full name to sign", whose value is the signature.
2. Refuse the form only when that field is empty, and move focus to it with the error.
3. Drop the signature library: nothing on the page draws any more.

This fixes the Before and passes 2.1.3 with the least code: every way of using the page can sign. What it gives up is the drawn mark, which some people expect when they sign.

## Which option to use

Both pass. Type or draw keeps the pad for people who expect to sign by hand, and costs a second field and a check that accepts either one. A typed name only is the smallest form and the least to maintain, and suits a business that has no use for the drawn mark. Choose by what the signature is for: if the business or a regulation needs the drawn mark kept, keep the pad beside the field; if the signature only records agreement, a typed name does that alone.

## Implementation decisions

Whether a typed name counts as a valid signature is a legal question for the business, not a technical one, and the answer depends on the agreement and the country. Several e-signature services offer a typed signature beside a drawn one, and some let the form's owner switch the typed one off, which can leave drawing as the only way to sign.

A Full name field and a typed signature both ask for the name. Don't fill the signature in from the name field, since then the person never signs anything; `autocomplete="name"` lets the browser offer it with one choice.

An upload of a picture of a signature is not enough on its own. A file input works from a keyboard, but someone who can't draw may have no picture of their signature to hand.

Making the pad draw with the arrow keys is not a fix either. A line drawn with arrow keys is not a signature, it is slow and hard work for anyone who presses keys with effort, and a screen reader user still can't see what they drew.

Some functions have no typed way at all: freehand drawing, painting, or a game steered along a path. Such content can't pass 2.1.3, and the W3C's notes on the criterion say so. A drawing tool can still give keyboard ways to everything that isn't a path, such as shapes, colours and moving what has been drawn, which 2.1.1 asks for.

If the drawing only stands for agreeing, as on many forms, the signing itself doesn't need a path, and a pad with no other way may fail 2.1.1 at Level A too. That failure belongs with [div buttons that can't be reached with Tab](/learn/native-buttons) and its topic; the fixes here mend both.

## Verify the fix

1. Put the mouse and touchpad aside. Tab through the form from the top, fill in every field, sign, and send it with a keyboard alone.
2. Sign with the typed field only, leaving the pad empty, and confirm the form is sent with no error.
3. With a screen reader, Tab to the signature, confirm the field's label is read (with the group's name, where the field sits in a group), type a name and send the form.
4. With voice control, say the field's label, dictate a name, and say the button's name to send it.

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the form or the signature library changes.

## Limits

This is a starting pattern, not a guarantee for every application. It shows how to give a signature a keyboard way; it doesn't decide whether a typed name is legally enough for your agreement. Dragging and other gestures with no single-pointer way are covered in [pinch, drag and tilt gestures with no button](/learn/gestures). Check the complete flow with people who rely on a keyboard, a switch, voice control or a screen reader.

---

Get this guide in your coding agent: MCP https://easeweb.dev/mcp (setup at https://easeweb.dev/services/developers)
