Avoid applying aria-valuenow, aria-valuemin, or aria-valuemax to a native <input type="number">. Assistive technologies may ignore these ARIA attributes in favor of the native properties, which can lead to inconsistent announcements if the values differ.
Spin button
Description
A spin button is an input widget that restricts its value to a set or range of discrete values. It is typically composed of a text field displaying the current value, along with increment and decrement buttons. Users can change the value by clicking the buttons, using arrow keys, or typing directly into the text field.
Spin buttons are a form of range widget, sharing characteristics with sliders (role="slider") and other range components. However, unlike a slider that operates along a visual track, a spin button presents its value as editable text and allows precise numeric entry.
A native HTML <input type="number"> provides spin button semantics automatically in most browsers. When a custom spin button is needed, the role="spinbutton" attribute must be explicitly set along with the appropriate ARIA range attributes.
When to use
- Use a spin button when the user needs to select a numeric value from a bounded or unbounded range with discrete steps (e.g., quantity selectors, day/month pickers, font size controls).
- Use a spin button when the user benefits from being able to type a value directly as well as increment or decrement it.
- Do not use a spin button for continuous ranges where a visual track aids selection — use a slider instead.
- Do not use a spin button for selecting from a list of non-numeric options — use a listbox or combobox instead.
Native HTML spin button
The native HTML <input type="number"> element provides built-in spin button semantics. Browsers render increment and decrement controls and expose the element with the spinbutton role to assistive technologies.
1<label for="quantity">Quantity:</label>2<input type="number" id="quantity" name="quantity" min="1" max="99" value="1" step="1" />
Native attributes min, max, value, and step define the spin button's range and behavior. Assistive technologies read these values without requiring any ARIA attributes.
Custom spin button
When a custom spin button is constructed using non-semantic HTML elements, the appropriate ARIA attributes must be applied to replicate the accessibility of the native element.
Custom spin button ARIA attributes
- Role: The element must have
role="spinbutton"to identify it as a spin button control. - Accessible name: Set
aria-labelledbyto theidof a visible label, or usearia-labelwhen no visible label is available. - Value: Set
aria-valuenowto the current numeric value. This attribute is required for the spin button to communicate its current state to assistive technologies. - Range boundaries: Set
aria-valueminandaria-valuemaxto define the allowed range. If the spin button has no defined minimum or maximum, omit the corresponding attribute. - Value text: Use
aria-valuetextto provide a human-readable alternative when the numeric value alone is not meaningful (e.g.,aria-valuetext="Monday"for a day-of-week picker wherearia-valuenow="2"). - Required: Set
aria-required="true"when the spin button must have a value for form submission. - Invalid: Set
aria-invalid="true"only when the current value fails validation (e.g., out of range). Remove or set to"false"when the value is valid. - Disabled: Use
aria-disabled="true"on custom spin buttons to convey the disabled state. For native<input type="number">, use thedisabledattribute instead.
Custom spin button code example
1<label id="qty-label">Quantity</label>2<div class="spinbutton-wrapper">3 <button tabindex="-1" aria-label="Decrease quantity">−</button>4 <div5 role="spinbutton"6 tabindex="0"7 aria-labelledby="qty-label"8 aria-valuenow="5"9 aria-valuemin="1"10 aria-valuemax="99"11 >12 513 </div>14 <button tabindex="-1" aria-label="Increase quantity">+</button>15</div>
Structure and semantics
All users must perceive and understand a spin button in order to use it. They must know its purpose, its current value, and the allowed range. Native HTML elements convey their semantic information to assistive technologies without requiring ARIA attributes. For custom spin buttons, the appropriate ARIA attributes must be applied to ensure equivalent accessibility.
Element has incorrect role
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Critical
Spin button components must have an ARIA role of spinbutton.
- A native HTML
<input type="number">has the implicitspinbuttonrole — no explicit role attribute is needed. - A custom spin button built from non-semantic elements must explicitly set
role="spinbutton"on the element that receives focus and displays the current value.
When the root element does not have the expected role, assistive technologies cannot interpret the element correctly and users may be confused about its purpose and behavior.
Missing contextual labeling
| Standard | Criteria |
|---|---|
| WCAG | 1.3.1 Info and Relationships |
| EN 301 549 | 9.1.3.1 Info and Relationships |
| Section 508 | N/A |
Impact: Critical
A spin button without an accessible name cannot be understood by screen reader users. The element relies on its visual context to convey its purpose, but that context must also be available programmatically.
- For native
<input type="number">, associate a<label>element using theforattribute. - For custom spin buttons, use
aria-labelledbyto reference theidof a visible label, or usearia-labelwhen no visible label is present.
Forbidden interactive children
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Serious
Interactive elements are nested within each other. Nesting interactive elements can negatively impact the navigation experience for screen reader users and keyboard operability for keyboard users.
Remove the inner element from the element that wraps it. If both elements are needed, restructure the component so that the interactive elements are siblings rather than parent-child.
Range values
Avoid ARIA values on native inputs
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Needs Review
Native HTML elements like <input type="number"> must not have the aria-valuenow, aria-valuemax, or aria-valuemin attributes. Assistive technologies may ignore these ARIA attributes and use the native value, min, and max attributes instead. If the ARIA and native values differ, users receive conflicting information.
Remove ARIA range attributes from native HTML spin button elements and use the native value, min, and max attributes to convey the current value and allowed range.
Missing range attributes
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Critical
A spin button must have attributes to convey its minimum, maximum, and current values to assistive technologies. Without aria-valuemin, aria-valuemax, and aria-valuenow, assistive technology users cannot perceive the range boundaries or the current value, making it impossible to use the component effectively.
Ensure the spin button includes aria-valuenow, aria-valuemin, and aria-valuemax set to the correct values. For native <input type="number">, use the value, min, and max attributes instead.
Range has equal min and max values
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Critical
The min and max attributes of the spin button are set to the same value. Users will not be able to select a value because the component will appear fixed at a single point.
Ensure the max attribute is greater than the min attribute so the spin button offers a meaningful range.
Min value is greater than the max value
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Critical
The spin button's minimum value is greater than or equal to its maximum value. Users will not be able to perceive the correct range or set their desired value.
Change the minimum value so that it is less than the maximum value.
Meaningful aria-valuetext
| Standard | Criteria |
|---|---|
| WCAG | N/A |
| EN 301 549 | N/A |
| Section 508 | N/A |
Impact: Best Practice
The aria-valuetext attribute on a spin button has the same value as the numeric aria-valuenow. Since aria-valuetext does not add extra context or meaning, screen reader users receive redundant information.
Use aria-valuetext only when the numeric value is not meaningful on its own or is difficult to understand (e.g., aria-valuetext="Monday" for a day-of-week picker). If the numeric value is sufficient and clear, remove the aria-valuetext attribute.
Invalid values
Value out of range
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Serious
The value of the spin button is set outside its defined minimum and maximum boundaries. Users may encounter unexpected behavior, and screen reader users may not know the correct range and could be confused by the invalid value.
Ensure the value of the spin button is always within the specified minimum and maximum. Update the code to validate and correct values that are out of range.
False aria-invalid value
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Serious
The aria-invalid attribute is set to true on a spin button even though the current value is within the valid range. Screen reader users will incorrectly believe the value is invalid, which can cause confusion or incorrect actions.
Set aria-invalid="true" only when the value is outside the valid range. When the value is valid, either set aria-invalid="false" or remove the attribute altogether.
Disabled
Element does not support the disabled attribute
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Serious
The disabled attribute is applied to a custom element with the spinbutton role. When used on an element that does not natively support it, the disabled attribute will not be read by screen readers, even if the element is removed from the focus sequence and all event listeners are removed.
Use aria-disabled="true" on custom spin button elements that do not support the native disabled attribute. For native <input type="number">, the disabled attribute works correctly.
Conflicting disabled values
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Serious
An element has disabled and aria-disabled attributes set to conflicting values. Assistive technologies may report the state of the element incorrectly, leading to confusion and misuse.
Use one attribute to indicate the disabled state:
- For native
<input type="number">, use thedisabledattribute only. - For custom spin button elements, use the
aria-disabledattribute only.
Relationships
A spin button often exists within a form alongside other controls. Its relationships with surrounding elements — such as labels, descriptions, and error messages — must be programmatically conveyed so that assistive technology users can understand its context.
- Associate a visible label using
<label for="...">for native inputs oraria-labelledbyfor custom spin buttons. - Associate helper text or error messages using
aria-describedby. - When the spin button is part of a form but not a DOM descendant of the
<form>element, usearia-ownson the form — though this should be avoided when possible.
Avoid aria-owns
| Standard | Criteria |
|---|---|
| WCAG | N/A |
| EN 301 549 | N/A |
| Section 508 | N/A |
Impact: Needs Review
The aria-owns attribute is being used to override the default parent/child relationship in the DOM. Some assistive technologies may not support aria-owns correctly, which can confuse users or present an incomplete representation of the component structure.
Avoid using aria-owns if possible. Instead, order the DOM elements in a way that naturally reflects the visual and logical structure. If aria-owns must be used, test thoroughly with different assistive technologies to ensure it works properly.
Operation
Pointer operation
A spin button typically includes increment and decrement buttons that respond to pointer clicks. The text field portion of the spin button may also accept direct text entry via pointer-initiated focus.
- Clicking the increment button increases the value by one step.
- Clicking the decrement button decreases the value by one step.
- Clicking the text field sets focus on it for direct value editing.
Keyboard operation
A spin button must be fully operable by keyboard. The following keyboard interactions are defined by the WAI-ARIA Authoring Practices spin button pattern:
Keyboard interaction
Increases the spin button value by one step.
Decreases the spin button value by one step.
If the spin button has a minimum value, sets the value to its minimum.
If the spin button has a maximum value, sets the value to its maximum.
Increases the value by a larger step than Up Arrow (e.g., by 10 instead of 1).
Decreases the value by a larger step than Down Arrow (e.g., by 10 instead of 1).
Focus remains on the spin button's text field during all keyboard interactions. Implementations should support platform-appropriate single-line text editing without JavaScript interference that blocks browser-native editing functions such as select-all, copy, and paste.
Focus sequence
Disabled element focusable
| Standard | Criteria |
|---|---|
| WCAG | N/A |
| EN 301 549 | N/A |
| Section 508 | N/A |
Impact: Needs Review
A native element that is supposedly disabled is included in the tab sequence. Keyboard users will be able to focus on an element that they cannot interact with, which may cause confusion and frustration.
Remove disabled elements from the tab sequence:
- Use
tabindex="-1"to remove the element from the tab sequence. - For native HTML controls, use the
disabledattribute, which automatically removes the element from the tab order.
Focusable offset
| Standard | Criteria |
|---|---|
| WCAG | 2.1.1 Keyboard |
| EN 301 549 | 9.2.1.1 Keyboard |
| Section 508 | N/A |
Impact: Needs Review
The element with the spinbutton role is not itself focusable — one of its descendants is incorrectly focusable instead. Screen reader users who tab through the interactive elements on the page will not perceive the element's type.
Ensure the element with role="spinbutton" is the focusable element, either by using a natively focusable element or by adding tabindex="0". Also ensure that the currently focusable descendant is removed from the tab order.
Keyboard accessible
| Standard | Criteria |
|---|---|
| WCAG | 2.1.1 Keyboard |
| EN 301 549 | 9.2.1.1 Keyboard |
| Section 508 | N/A |
Impact: Critical
The spin button element is missing the right tags or has incorrect tags, excluding it from the keyboard tab sequence. Keyboard users cannot reach or operate the spin button.
When the spin button is not focusable, the tester will also skip all keyboard navigation and value-change tests — meaning the full extent of keyboard accessibility issues may be underreported until this is fixed.
Use one of these approaches:
- Approach 1 (recommended): Use a native
<input type="number">, which is focusable by default. - Approach 2: Add
tabindex="0"to the custom spin button element.
Focus lost after spin button interaction
| Standard | Criteria |
|---|---|
| WCAG | 3.2.2 On input |
| EN 301 549 | 9.3.2.2 On input |
| Section 508 | N/A |
Impact: Serious
Upon pressing the Up Arrow, Down Arrow, Home, End, Page Up, or Page Down keys, focus unexpectedly moves away from the spin button element. Keyboard users will find it difficult to operate the spin button when focus is lost after each interaction.
Implement proper keyboard handling to ensure that arrow keys, Home, End, Page Up, and Page Down modify the spin button's value without shifting focus away from the spin button element.
Keyboard navigation
Spin button does not support Home key
| Standard | Criteria |
|---|---|
| WCAG | 2.1.1 Keyboard |
| EN 301 549 | 9.2.1.1 Keyboard |
| Section 508 | N/A |
Impact: Moderate
The spin button has a minimum value but does not update to this value when the Home key is pressed. Users who rely on keyboard navigation may struggle to quickly move to the minimum value.
Ensure pressing the Home key sets the spin button's value to its minimum. Add an event listener for the Home key that sets aria-valuenow (or the native value) to the minimum value accordingly.
Spin button does not support End key
| Standard | Criteria |
|---|---|
| WCAG | 2.1.1 Keyboard |
| EN 301 549 | 9.2.1.1 Keyboard |
| Section 508 | N/A |
Impact: Moderate
The spin button has a maximum value but does not update to this value when the End key is pressed. Users who rely on keyboard navigation may struggle to quickly move to the maximum value.
Ensure pressing the End key sets the spin button's value to its maximum. Add an event listener for the End key that sets aria-valuenow (or the native value) to the maximum value accordingly.
Spin button value unchanged with keyboard
| Standard | Criteria |
|---|---|
| WCAG | 2.1.1 Keyboard |
| EN 301 549 | 9.2.1.1 Keyboard |
| Section 508 | N/A |
Impact: Critical
The aria-valuenow attribute of the spin button does not update when the user presses the Up Arrow, Down Arrow, Page Up, or Page Down keys. Keyboard-only users and screen reader users will not know if the value changed, making it difficult or impossible to use the control effectively.
Ensure aria-valuenow is updated whenever the user interacts with the spin button using the Up Arrow, Down Arrow, Page Up, or Page Down keys. The attribute must accurately reflect the current value at all times.
Unexpected spin button value
| Standard | Criteria |
|---|---|
| WCAG | 4.1.2 Name, Role, Value |
| EN 301 549 | 9.4.1.2 Name, Role, Value |
| Section 508 | 1194.21(d) |
Impact: Serious
When pressing a keyboard key at a boundary value, the spin button's aria-valuenow changes to a value outside the allowed range or to an invalid value. Screen reader users may be confused and unable to properly interact with the control.
Ensure the following:
- The
aria-valuenowvalue does not exceedaria-valuemaxor fall belowaria-valuemin. - When
aria-valuenowreachesaria-valuemaxand the user attempts to increment, maintainaria-valuenowataria-valuemax. - When
aria-valuenowreachesaria-valueminand the user attempts to decrement, maintainaria-valuenowataria-valuemin.
Disabled spin button operable
| Standard | Criteria |
|---|---|
| WCAG | 1.3.1 Info and Relationships |
| EN 301 549 | 9.1.3.1 Info and Relationships |
| Section 508 | N/A |
Impact: Moderate
The spin button appears to be disabled but still responds to keyboard events. Users relying on screen readers or keyboards can still interact with the spin button even though it appears disabled, causing confusion or unintended actions.
Ensure the spin button is programmatically disabled using the disabled attribute on native <input type="number"> elements. For custom spin buttons, ensure aria-disabled="true" is set and that keyboard events are not processed when the spin button is disabled.
Deprecated keypress listener
| Standard | Criteria |
|---|---|
| WCAG | N/A |
| EN 301 549 | N/A |
| Section 508 | N/A |
Impact: Needs Review
The spin button component is using the keypress event listener, which is deprecated. The keypress event might not trigger as expected, leading to potential issues in functionality for users relying on keyboard interactions.
Replace keypress event listeners with either keydown or keyup event listeners.