StartFoundationsComponentsContent

Number input

A number input takes a number people type, such as an amount, a price, a rate, or a measurement. It can format the value as currency, a percent, or a unit, and has small ▲▼ buttons to step it. Wrap it in a Field for a label.

Stable Figma
OverviewUsageAPIAccessibility
<tk-field label="Amount">
  <tk-number-input name="amount" format="currency" currency="USD" min="0" step="0.01" value="1234.5"></tk-number-input>
</tk-field>

Anatomy

Part What it is
tk-number-input the element; one Tab stop
field part the bordered box
input part the inner text field with the spinbutton role
prefix / suffix slots optional text or icon before or after the value
spinners part the ▲▼ pair at the trailing edge; press to step, hold to repeat

The label, help text, and error message come from a Field.

Formatting

<tk-field label="Price">
  <tk-number-input format="currency" currency="EUR" value="1250"></tk-number-input>
</tk-field>
<tk-field label="Completion">
  <tk-number-input format="percent" value="0.5" step="0.01"></tk-number-input>
</tk-field>
%
<tk-field label="Discount">
  <tk-number-input min="0" max="100" step="5" value="20"><span slot="suffix">%</span></tk-number-input>
</tk-field>
  • At rest, the field shows the formatted value ("$1,234.50"). On focus it shows the plain number ("1234.5"), so typing never fights separators. value stays a plain number.
  • format: decimal (default), currency with a currency code (USD if unset), percent, or unit with a unit such as kilometer. precision fixes the decimal places; locale sets the separators.
  • format="percent" treats the value as a fraction: 0.5 shows "50%". If your value is already 50, use a % suffix instead.
  • Affixes are decoration and are hidden from screen readers. Use format when the unit is part of the value.
  • For anything else Intl.NumberFormat supports, set the formatOptions property. It overrides the shorthand attributes.

Value and stepping

  • min, max, and step define the allowed values. People can type anything; when they leave the field, press Enter, or step, the value is clamped to the range and snapped to step.
  • ▲▼ and the arrow keys change the value by step. Page Up, Page Down, and Shift with an arrow use large-step (a tenth of the range, or step × 10 with no range).
  • At min or max, the matching button is disabled. Stepping an empty field starts at min, or 0.
  • Negative numbers can be typed unless min is 0 or more.
  • The scroll wheel doesn't change the value. Set wheel to allow it, only while the field has focus.

Sizes

<tk-number-input aria-label="Medium number input" value="12"></tk-number-input>
<tk-number-input aria-label="Large number input" size="large" value="12"></tk-number-input>
size Height Padding-inline (start) Value text
medium (default) 32px space-8 Body Small (14/20)
large 36px space-10 Body Medium (16/24)

The heights match medium and large buttons. There is no small; size="small" renders as medium and logs a console warning.

States

<tk-number-input aria-label="Seats included" value="25" readonly></tk-number-input>
<tk-number-input aria-label="Seats" value="25" disabled></tk-number-input>
<tk-field label="Seats" required error="Enter a number of seats from 1 to 500">
  <tk-number-input name="seats" min="1" max="500" value="900"></tk-number-input>
</tk-field>

The box works like an Input: no change on hover, and on focus its border takes the focus color and grows thicker inward. The ▲▼ buttons tint under the pointer.

  • readonly: people can focus and copy the value, but not change it. The ▲▼ buttons are hidden.
  • disabled: the field can't be focused or changed, and it's left out of the form.
  • Error: set error on the Field. The field clamps an out-of-range value but never shows an error on its own; you decide when and what to say.
  • Required: set required on the Field. Without a Field, set it on the number input.