Skip to main content

Input mask

Guide people toward a valid format as they type with an input mask for constrained text fields.

Example

Breakpoints

Mobile

320px

Mobile Lg

480px

Tablet

640px

Desktop

1024px
For example, 123 45 6789
For example, 123-456-7890
For example, 12345-6789
For example, A1B 2C3
HTML
<div class="space-y-12">
<div class="max-w-xs" data-scope="input-mask" data-part="root" id="mask-ssn">
<label for="input-mask:mask-ssn:input" class="block">Social Security Number</label>
<div id="hint-ssn" class="text-gray-50">For example, 123 45 6789</div>
<div class="relative mt-2">
<div aria-hidden="true" class="absolute inset-0 p-2 pointer-events-none border inline-flex whitespace-pre">
<span data-scope="input-mask" data-part="content" class="text-gray-50 [&>i]:invisible [&>i]:not-italic"></span>
</div>
<input id="input-mask:mask-ssn:input" data-scope="input-mask" data-part="input" inputmode="numeric" autocomplete="off" placeholder="___ __ ____" aria-describedby="hint-ssn" class="p-2 w-full h-10 border border-gray-60 focus:outline-offset-0 focus:outline-4 focus:outline-blue-40v placeholder:invisible" />
</div>
</div>
<div class="max-w-xs" data-scope="input-mask" data-part="root" id="mask-phone">
<label for="input-mask:mask-phone:input" class="block">US Telephone Number</label>
<div id="hint-phone" class="text-gray-50">For example, 123-456-7890</div>
<div class="relative mt-2">
<div aria-hidden="true" class="absolute inset-0 p-2 pointer-events-none border inline-flex whitespace-pre">
<span data-scope="input-mask" data-part="content" class="text-gray-50 [&>i]:invisible [&>i]:not-italic"></span>
</div>
<input id="input-mask:mask-phone:input" data-scope="input-mask" data-part="input" inputmode="tel" autocomplete="tel" placeholder="___-___-____" aria-describedby="hint-phone" class="p-2 w-full h-10 border border-gray-60 focus:outline-offset-0 focus:outline-4 focus:outline-blue-40v placeholder:invisible" />
</div>
</div>
<div class="max-w-xs" data-scope="input-mask" data-part="root" id="mask-zip">
<label for="input-mask:mask-zip:input" class="block">ZIP Code</label>
<div id="hint-zip" class="text-gray-50">For example, 12345-6789</div>
<div class="relative mt-2">
<div aria-hidden="true" class="absolute inset-0 p-2 pointer-events-none border inline-flex whitespace-pre">
<span data-scope="input-mask" data-part="content" class="text-gray-50 [&>i]:invisible [&>i]:not-italic"></span>
</div>
<input id="input-mask:mask-zip:input" data-scope="input-mask" data-part="input" inputmode="numeric" autocomplete="postal-code" placeholder="_____-____" aria-describedby="hint-zip" class="p-2 w-full h-10 border border-gray-60 focus:outline-offset-0 focus:outline-4 focus:outline-blue-40v placeholder:invisible" />
</div>
</div>
<div class="max-w-xs" data-scope="input-mask" data-part="root" id="mask-alpha">
<label for="input-mask:mask-alpha:input" class="block">Alphanumeric</label>
<div id="hint-alpha" class="text-gray-50">For example, A1B 2C3</div>
<div class="relative mt-2">
<div aria-hidden="true" class="absolute inset-0 p-2 pointer-events-none border inline-flex whitespace-pre">
<span data-scope="input-mask" data-part="content" class="text-gray-50 [&>i]:invisible [&>i]:not-italic"></span>
</div>
<input id="input-mask:mask-alpha:input" data-scope="input-mask" data-part="input" data-charset="A#A #A#" autocomplete="off" placeholder="___ ___" aria-describedby="hint-alpha" class="p-2 w-full h-10 border border-gray-60 focus:outline-offset-0 focus:outline-4 focus:outline-blue-40v placeholder:invisible" />
</div>
</div>
</div>

Component API

Initialization

Run after the component markup exists:

import { inputMaskInit } from '@uswds-tailwind/compat/input-mask'
inputMaskInit()

Anatomy

Set authored attributes in your HTML. The component manages generated attributes. Types describe HTML attribute values.

root

Wraps the input and mask overlay.

Attribute Type Description
data-scope "input-mask" Authored. Identifies the component scope.
data-part "root" Authored. Identifies this part.

input

Required native input.

Attribute Type Description
data-part "input" Authored. Identifies this part.
placeholder string Authored. Mask format, such as ___-___-____. The mask option takes precedence.
data-charset string Authored. Character rules, such as A#A #A#: A accepts a letter and # a digit. The charset option takes precedence.
value string Authored. Initial value; the defaultValue option takes precedence.
pattern string Authored. Native browser validation pattern; does not configure the mask.
maxlength integer Generated. Derived from the mask.
data-placeholder string Generated. Derived from the mask; the native placeholder is removed.
id string Generated. Defaults to input-mask:<root-id>:input; use ids.input to override.

content

Required overlay. The runtime generates children for entered text and the remaining mask. Style the generated i with visibility: hidden and normal font style to reserve space for entered text.

Attribute Type Description
data-part "content" Authored. Identifies this part.

Configuration

Pass these JavaScript options to the instance constructor or factory. Authored configuration attributes are read during construction.

Option Description
mask string. Mask format; overrides the input placeholder.
charset string. Character rules; overrides data-charset.
defaultValue string. Initial value; overrides the input value.
value string. Controlled value; takes precedence over the default.
ids.input Custom input ID for label composition.

Methods

Method Returns Description
api.setValue(value) void Requests a formatted value update.
destroy() void Stops the instance; does not restore original markup.
import { InputMask } from '@uswds-tailwind/compat/input-mask'
const mask = InputMask.getOrCreateInstance(
'[data-scope="input-mask"][data-part="root"]',
)
mask.api.setValue('2025550123')

See initialization and cleanup.

Callbacks

Callback Payload When it runs
onValueChange { value: string } The formatted value changes or a controlled change is requested.

Pass callbacks in instance options. These are JavaScript functions, not emitted DOM events.

Behavior

Uncontrolled typing formats on keyup. Controlled typing proposes formatted changes on input. The mask does not infer invalid state from partial input; native pattern and form attributes determine validity.

Accessibility

  • Link the label to the generated input ID, or supply ids.input.
  • Keep a visible format hint and connect it with aria-describedby.
  • For a controlled value, your application must supply updates after change callbacks. See shared lifecycle.