Number Field

Numeric input with increment and decrement stepper controls. Supports min/max constraints, step value, arrow key increments, and format display for currency and percent values.

Anatomy

1 2 3
  1. 1 Format prefix/suffix — optional currency ($) or percent (%) indicator
  2. 2 Input primitive — numeric text entry element (value or placeholder)
  3. 3 Stepper controls — decrement and increment buttons

Options

States

Default
Hover
Focus
Disabled

Format display

None (default)
Currency
Percent

Table of options

PropertyValuesDefault
valuenumber
minnumber
maxnumber
stepnumber1
formatnone / currency / percentnone
placeholdertext0
disabledtrue / falsefalse
statedefault / hover / active / focus / disabled / readonly / invaliddefault

Behaviors

Stepper buttons

Minus and plus buttons increment or decrement the value by the configured step amount. JavaScript enhancement via input-field.js handles click events.

Min/max constraints

The min and max attributes constrain the accepted range. The stepper clamps to these bounds. Arrow key increments also respect constraints.

Custom step

The step attribute controls the increment amount for both button clicks and arrow key presses. Fractional steps are supported.

Currency format

The format="currency" option prepends a $ symbol as a decorative, non-interactive prefix. For localised currency formatting, provide the symbol via the prefix slot.

Percent format

The format="percent" option appends a % symbol as a decorative suffix after the input.

Disabled state

A disabled number field cannot be edited or stepped. It is removed from the tab order and stepper buttons are visually hidden.

Usage guidelines

Always pair with a label

<label for="qty">Quantity</label>

Do

Every number field must have a visible label, aria-label, or aria-labelledby.

Don't

Do not render a number field without an associated label or accessible name.

Use min/max to communicate range

Do

Set min and max to prevent out-of-range entries and constrain stepper buttons.

Don't

Avoid displaying a percent field without min="0" max="100" constraints.

Code

HTML

<!-- Plain number field -->
<div class="uif-input-field uif-number-field">
  <input class="uif-input" type="number" placeholder="0" value="0" />
  <span class="uif-input-field-control">
    <button type="button" aria-label="Decrease value"><!-- minus icon --></button>
    <button type="button" aria-label="Increase value"><!-- plus icon --></button>
  </span>
</div>

<!-- Currency format -->
<div class="uif-input-field uif-number-field">
  <span class="uif-number-field-prefix" aria-hidden="true">$</span>
  <input class="uif-input" type="number" placeholder="0" value="9.99" step="0.01" />
  <span class="uif-input-field-control">
    <button type="button" aria-label="Decrease value"><!-- minus icon --></button>
    <button type="button" aria-label="Increase value"><!-- plus icon --></button>
  </span>
</div>

<!-- Percent format -->
<div class="uif-input-field uif-number-field">
  <input class="uif-input" type="number" placeholder="0" value="75" min="0" max="100" />
  <span class="uif-number-field-suffix" aria-hidden="true">%</span>
  <span class="uif-input-field-control">
    <button type="button" aria-label="Decrease value"><!-- minus icon --></button>
    <button type="button" aria-label="Increase value"><!-- plus icon --></button>
  </span>
</div>

Web Component

<uif-number-field value="0" step="1" aria-label="Quantity"></uif-number-field>
<uif-number-field format="currency" value="9.99" step="0.01" aria-label="Price"></uif-number-field>
<uif-number-field format="percent" value="75" min="0" max="100" aria-label="Progress"></uif-number-field>

Nunjucks macro


<div class="uif-input-field uif-number-field"><input class="uif-input" type="number" placeholder="0" value="0" step="1" /><span class="uif-input-field-control">
    <button type="button" aria-label="Decrease value"><span class="uif-icon" style="--uif-icon-src: url('/assets/icons/minus-circled.svg');" aria-hidden="true"></span></button>
    <button type="button" aria-label="Increase value"><span class="uif-icon" style="--uif-icon-src: url('/assets/icons/plus-circled.svg');" aria-hidden="true"></span></button>
  </span>
</div>
<div class="uif-input-field uif-number-field"><span class="uif-number-field-prefix" aria-hidden="true">$</span><input class="uif-input" type="number" placeholder="0" value="9.99" step="0.01" /><span class="uif-input-field-control">
    <button type="button" aria-label="Decrease value"><span class="uif-icon" style="--uif-icon-src: url('/assets/icons/minus-circled.svg');" aria-hidden="true"></span></button>
    <button type="button" aria-label="Increase value"><span class="uif-icon" style="--uif-icon-src: url('/assets/icons/plus-circled.svg');" aria-hidden="true"></span></button>
  </span>
</div>
<div class="uif-input-field uif-number-field"><input class="uif-input" type="number" placeholder="0" value="75" min="0" max="100" /><span class="uif-number-field-suffix" aria-hidden="true">%</span><span class="uif-input-field-control">
    <button type="button" aria-label="Decrease value"><span class="uif-icon" style="--uif-icon-src: url('/assets/icons/minus-circled.svg');" aria-hidden="true"></span></button>
    <button type="button" aria-label="Increase value"><span class="uif-icon" style="--uif-icon-src: url('/assets/icons/plus-circled.svg');" aria-hidden="true"></span></button>
  </span>
</div>

Accessibility

  • The <input type="number"> element is natively keyboard accessible: arrow keys increment or decrement by the configured step, Home/End jump to min/max.
  • Stepper buttons have descriptive aria-label values ("Decrease value" / "Increase value").
  • Format prefix and suffix elements carry aria-hidden="true" to avoid duplicate announcements; the accessible label or surrounding <label> should convey the unit context.
  • Disabled fields are removed from the tab order via the native disabled attribute.