Signature
<quiet-signature>
Allows users to capture signatures by drawing on a canvas or typing their name.
The signature component includes a text field that is always visible for accessibility. This ensures keyboard users can provide their signature by typing their name, while touch/mouse users can draw directly on the canvas.
Drawing and typing are mutually exclusive — starting one clears the other. Typed names are rendered on the canvas using a customizable cursive font, ensuring consistent output regardless of input method.
<quiet-signature name="signature" label="Your signature"></quiet-signature>
Examples Jump to heading
Labels and descriptions Jump to heading
You can use the label and description attributes to provide plain text labels and
descriptions for the signature field. If you want to provide HTML, use the label and
description slots instead.
<quiet-signature name="signature" label="Signature"> <span slot="description"> By signing, you agree to the <a href="https://example.com/" target="_blank">terms and conditions</a>. </span> </quiet-signature>
Submitting signatures Jump to heading
When a signature field is inside a form, its value is submitted with the form data using the
name attribute as the key. Both drawn and typed signatures are submitted as Base64-encoded PNG
data URIs (e.g., data:image/png;base64,...). On the server, you can decode the Base64 data to
save the signature as an image file.
<div id="signature__form"> <form> <quiet-signature name="signature" label="Signature"></quiet-signature> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> </form> <pre style="max-width: 100%; overflow: auto; margin-block: 1.5rem 0;" hidden></pre> </div> <script type="module"> import { allDefined } from '/dist/quiet.js'; await allDefined(); const container = document.getElementById('signature__form'); const form = container.querySelector('form'); const output = container.querySelector('pre'); form.addEventListener('submit', event => { const formData = new FormData(form); const signature = formData.get('signature'); output.hidden = false; event.preventDefault(); if (signature) { output.textContent = signature.substring(0, 100) + '...'; } else { output.textContent = 'No signature provided'; } }); </script>
Controlling the exported image Jump to heading
Use the export-width and export-height attributes to control the dimensions of the
exported signature image. This affects both getImage() and the value submitted with forms.
The default width is 800 pixels, which ensures signatures remain crisp on high-density
displays. Height is automatically calculated unless a special export-height is set.
Use export-ink-color to export signatures with a different ink color than what's displayed on
screen. The image's background is always transparent.
<div id="signature__export"> <form> <quiet-signature name="signature" label="Sign below" export-width="800" export-height="800" export-ink-color="deeppink" required ></quiet-signature> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> <quiet-button type="reset">Reset</quiet-button> </form> <div style="margin-top: 1rem;" hidden> Exported image (square, deeppink) <br> <img style="width: 200px; height: 200px; margin-top: 0.5rem; border: 1px solid var(--quiet-neutral-stroke-soft);"> </div> </div> <script type="module"> import { allDefined } from '/dist/quiet.js'; await allDefined(); const container = document.getElementById('signature__export'); const form = container.querySelector('form'); const signature = container.querySelector('quiet-signature'); const result = container.querySelector('div'); const img = container.querySelector('img'); form.addEventListener('submit', event => { event.preventDefault(); const image = signature.getImage(); if (image) { img.src = image; result.hidden = false; } }); form.addEventListener('reset', () => { result.hidden = true; img.src = ''; }); </script>
Custom ink color and width Jump to heading
Use the --ink-color custom property to change the color of the drawn signature. Use
--ink-width to change the stroke width (default: 2).
<quiet-signature name="signature" label="Colored signature" style="--ink-color: var(--quiet-primary-fill-mid);" ></quiet-signature> <br> <quiet-signature name="signature" label="Thicker signature" style="--ink-width: 6;" ></quiet-signature> <br> <quiet-signature name="signature" label="Thinner signature" style="--ink-width: 1.5;" ></quiet-signature>
Custom fonts Jump to heading
Typed names are rendered on the canvas using a cursive font. Use the
--signature-font-family custom property to change the font. The default is
cursive, which uses the system's cursive font.
<quiet-signature name="signature" label="Signature with custom font" style="--signature-font-family: 'Brush Script MT', 'Segoe Script', cursive;" ></quiet-signature>
You can also use web fonts like Google Fonts. Make sure to load the font before using it.
<link href="https://fonts.googleapis.com/css2?family=Dancing+Script&display=swap" rel="stylesheet"> <quiet-signature name="signature" label="Signature with Google Font" style="--signature-font-family: 'Dancing Script', cursive;" ></quiet-signature>
You can also control the font weight with --signature-font-weight, and the minimum and maximum
font sizes that will be displayed with --signature-font-size-min and
--signature-font-size-max.
<quiet-signature name="signature" label="Signature with bold font" style="--signature-font-weight: bold;" ></quiet-signature>
Custom placeholders Jump to heading
Use the placeholder attribute to change the text field's placeholder. Use the
signature-placeholder attribute to change the placeholder shown in the signature box.
The signature box also supports HTML placeholders through the signature-placeholder slot, as
shown below.
scribble here
<quiet-signature name="signature" label="Signature" signature-placeholder="Draw your signature here" placeholder="Or you can type in your name here" > <div slot="signature-placeholder"> <quiet-icon name="signature" style="font-size: 3em;"></quiet-icon> <br> scribble here </div> </quiet-signature>
Changing the size Jump to heading
Use the size attribute to change the signature field's size.
<quiet-select label="Select a size" value="xs" style="max-width: 18rem; margin-block-end: 2rem;"> <option value="xs">Extra small</option> <option value="sm">Small</option> <option value="md" selected>Medium</option> <option value="lg">Large</option> <option value="xl">Extra large</option> </quiet-select> <quiet-signature id="signature__size" name="signature" label="Signature" size="xs" ></quiet-signature> <script> const signature = document.getElementById('signature__size'); const select = signature.previousElementSibling; select.addEventListener('quiet-change', () => { signature.size = select.value; }); </script>
Disabling Jump to heading
Use the disabled attribute to disable the signature field.
<quiet-signature label="Disabled signature" disabled></quiet-signature>
Read-only Jump to heading
Use the readonly attribute to make the signature field read-only. The user can see any existing
signature but cannot modify it.
<quiet-signature label="Read-only signature" readonly></quiet-signature>
Validation Jump to heading
The required attribute can be used to make the signature field required. The form will not
submit until the user provides a signature (drawn or typed).
<form action="about:blank" method="get" target="_blank"> <quiet-signature name="signature" label="Signature" required ></quiet-signature> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> <quiet-button type="reset">Reset</quiet-button> </form>
Using custom validation Jump to heading
Use the setCustomValidity() method to make the signature field invalid and show a custom error
message on submit. This will override all other validation parameters. To clear the error, call it with an
empty string.
<form action="about:blank" method="get" target="_blank" id="signature__custom-validation"> <quiet-signature name="signature" label="Signature" description="This field will be invalid until custom validation is removed" ></quiet-signature> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> </form> <script type="module"> import { allDefined } from '/dist/quiet.js'; await allDefined(); const form = document.getElementById('signature__custom-validation'); const signature = form.querySelector('quiet-signature'); signature.setCustomValidity('This field will be invalid until custom validation is removed'); </script>
Styling validation Jump to heading
You can style valid and invalid signature fields using the :valid and
:invalid pseudo classes.
<form action="about:blank" method="get" target="_blank" class="signature__validation-pseudo"> <quiet-signature name="signature" label="Signature" description="This field is required" required ></quiet-signature> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> <quiet-button type="reset">Reset</quiet-button> </form> <style> .signature__validation-pseudo { quiet-signature:valid { outline: solid 2px var(--quiet-constructive-stroke-mid); outline-offset: .5rem; } quiet-signature:invalid { outline: solid 2px var(--quiet-destructive-stroke-mid); outline-offset: .5rem; } } </style>
However, these selectors will match even before the user has had a chance to interact with the form. More
often than not, you'll want to use the user-valid and user-invalid
custom states instead. This way, validation styles are only shown
after the user interacts with the form control or when the form is submitted.
<form action="about:blank" method="get" target="_blank" class="signature__validation-custom"> <quiet-signature name="signature" label="Signature" description="This field is required" required ></quiet-signature> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> <quiet-button type="reset">Reset</quiet-button> </form> <style> .signature__validation-custom { quiet-signature:state(user-valid) { outline: solid 2px var(--quiet-constructive-stroke-mid); outline-offset: .5rem; } quiet-signature:state(user-invalid) { outline: solid 2px var(--quiet-destructive-stroke-mid); outline-offset: .5rem; } } </style>
API Jump to heading
Importing Jump to heading
The autoloader is the recommended way to import components but, if you prefer to do it manually, the following code snippets will be helpful.
To manually import <quiet-signature> from the CDN, use the following code.
import 'https://cdn.quietui.org/v2.4.0/components/signature/signature.js';
To manually import <quiet-signature> from a self-hosted distribution, use the
following code. Remember to replace /path/to/quiet with the appropriate local path.
import '/path/to/quiet/components/signature/signature.js';
Slots Jump to heading
Signature supports the following slots. Learn more about using slots
| Name | Description |
|---|---|
label
|
The signature field's label. For plain-text labels, you can use the label attribute
instead.
|
description
|
The signature field's description. For plain-text descriptions, you can use the
description attribute instead.
|
signature-placeholder
|
The placeholder to render in the signature box. |
Properties Jump to heading
Signature has the following properties that can be set with corresponding attributes. In many cases, the attribute's name is the same as the property's name. If an attribute is different, it will be displayed after the property. Learn more about attributes and properties
| Property / Attribute | Description | Reflects | Type | Default |
|---|---|---|---|---|
label
|
The signature field's label. If you need to provide HTML in the label, use the
label slot instead.
|
|
string
|
|
description
|
The signature field's description. If you need to provide HTML in the description, use the
description slot instead.
|
|
string
|
|
name
|
The name of the signature field. This will be submitted with the form as a name/value pair. |
|
string
|
|
value
|
The signature field's value. When a signature is drawn, this will be a Base64 data URI. When typed, this will be the typed text. |
|
string
|
''
|
signaturePlaceholder
signature-placeholder
|
The placeholder text shown when the canvas is empty. Defaults to a localized "Sign here" message. |
|
string
|
''
|
placeholder
|
The placeholder text for the text field. Defaults to a localized "Type your full name" message. |
|
string
|
''
|
disabled
|
Disables the signature field. |
|
boolean
|
false
|
readonly
|
Makes the signature field read-only. |
|
boolean
|
false
|
required
|
Makes the signature field required. Form submission will not be allowed when this is set and no signature or typed name exists. |
|
boolean
|
false
|
size
|
The signature field's size. |
|
'xs'
|
'md'
|
exportWidth
export-width
|
The width of the exported image in pixels. Height is auto-calculated to preserve the canvas aspect
ratio unless
export-height is also set.
|
|
number
|
800
|
exportHeight
export-height
|
The height of the exported image in pixels. If only export-height is set, width is
calculated to preserve the canvas aspect ratio. If both export-width and
export-height are set, the signature is scaled to fit within the bounds while
preserving aspect ratio.
|
|
number
|
|
exportInkColor
export-ink-color
|
The ink color used when exporting via getImage(). When set, allows the UI to display
one color (e.g. for dark mode) while exporting with a different color (e.g. black for transparent
backgrounds). If not set, defaults to the current --ink-color.
|
|
string
|
|
form
|
The form to associate this control with. If omitted, the closest containing
<form> will be used. The value of this attribute must be an ID of a form in the
same document or shadow root.
|
|
string
|
Methods Jump to heading
Signature supports the following methods. You can obtain a reference to the element and call them like functions in JavaScript. Learn more about methods
| Name | Description | Arguments |
|---|---|---|
focus() |
Sets focus to the text field. | |
blur() |
Removes focus from the signature field. | |
clear() |
Clears the signature and typed name. | |
getImage() |
Returns the signature as a data URI, or returns null if no signature exists.
|
format: 'png' <br> 'jpeg'
|
checkValidity() |
Checks if the form control has any restraints and whether it satisfies them. If invalid,
false will be returned and the invalid event will be dispatched. If valid,
true will be returned.
|
|
reportValidity() |
Checks if the form control has any restraints and whether it satisfies them. If invalid,
false will be returned and the invalid event will be dispatched. In
addition, the problem will be reported to the user. If valid, true will be returned.
|
|
setCustomValidity()
|
Sets a custom validation message for the form control. If this message is not an empty string, then the form control is considered invalid and the specified message will be displayed to the user when reporting validity. Setting an empty string clears the custom validity state. | message: string |
Events Jump to heading
Signature dispatches the following custom events. You can listen to them the same way was native events. Learn more about custom events
| Name | Description |
|---|---|
quiet-blur |
Emitted when the signature field loses focus. This event does not bubble. |
quiet-change |
Emitted when the user commits changes to the signature field's value. |
quiet-focus |
Emitted when the signature field receives focus. This event does not bubble. |
quiet-input |
Emitted when the signature field receives input. |
CSS custom properties Jump to heading
Signature supports the following CSS custom properties. You can style them like any other CSS property. Learn more about CSS custom properties
| Name | Description | Default |
|---|---|---|
--ink-color |
The color of the drawn or typed signature. |
var(--quiet-text-body)
|
--ink-width |
The stroke width in pixels. |
2
|
--signature-font-family |
The font family used for typed signatures. |
cursive
|
--signature-font-weight |
The font weight used for typed signatures. |
normal
|
--signature-font-size-min |
The minimum font size in pixels for typed signatures. |
16
|
--signature-font-size-max |
The maximum font size in pixels for typed signatures. |
64
|
CSS parts Jump to heading
Signature exposes internal elements that can be styled with CSS using the selectors shown below. Learn more about CSS parts
| Name | Description | CSS selector |
|---|---|---|
label |
The element that contains the signature field's label. |
::part(label)
|
description |
The element that contains the signature field's description. |
::part(description)
|
signature-box |
The container that wraps the canvas. |
::part(signature-box)
|
canvas |
The drawing canvas element. |
::part(canvas)
|
signature-placeholder |
The placeholder text shown when the signature box empty. |
::part(signature-placeholder)
|
clear-button |
The clear button that appears when a signature exists. |
::part(clear-button)
|
type-field |
The text field for typing a name, an <input> element.
|
::part(type-field)
|
Custom States Jump to heading
Signature has the following custom states. You can target them with CSS using the selectors shown below. Learn more about custom states
| Name | Description | CSS selector |
|---|---|---|
disabled |
Applied when the signature field is disabled. |
:state(disabled)
|
blank |
Applied when the signature field has no signature or typed name. |
:state(blank)
|
focused |
Applied when the signature field has focus. |
:state(focused)
|
user-valid |
Applied when the signature field is valid and the user has sufficiently interacted with it. |
:state(user-valid)
|
user-invalid |
Applied when the signature field is invalid and the user has sufficiently interacted with it. |
:state(user-invalid)
|
Dependencies Jump to heading
Signature automatically imports the following elements. Sub-dependencies are also included in this list.