advanced forms
Tailwind CSS Input Number
The Input Number, also called Quantity Selector, lets users specify quantities easily. Ideal for selecting product amounts or seat numbers, it offers simple increment and decrement controls, making numeric input smooth for e-commerce and more.
Class Name | Type | Description |
---|---|---|
input | Component | Basic input field. |
input-group | Component | Adds inline addons to inputs. |
input-number-disabled:{tw-utility-class} | Modifier | The modifier allows setting Tailwind classes when input’s value is set to zero. |
is-valid | Modifier | Adds success style to the input. |
is-invalid | Modifier | Adds error style to the input. |
Basic example of input number.
Enclose the data-input-number-input
and data-input-number-decrement
elements of the input-number within data-input-number-increment
within data-input-number
.
<div class="input-group max-w-sm" data-input-number>
<input class="input" type="text" value="1" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Input number with label.
<label class="label-text" for="number-input-label">Quantity:</label>
<div class="input-group max-w-sm" data-input-number>
<input class="input" id="number-input-label" type="text" value="0" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Success state can be show using is-valid
class.
<div class="input-group max-w-sm" data-input-number>
<input class="input is-valid" valid type="text" value="1" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Error state can be show using is-invalid
class.
<div class="input-group max-w-sm" data-input-number>
<input class="input is-invalid" type="text" value="1" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Basic disabled state.
<div class="input-group max-w-sm" data-input-number>
<input class="input" type="text" value="1" data-input-number-input disabled />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Vertically stacked buttons example.
<label class="label-text" for="number-input-vertically">Quantity:</label>
<div class="input-group max-w-sm rounded-tooltip" data-input-number>
<input class="input" id="number-input-vertically" type="text" value="0" data-input-number-input />
<span class="input-group-text divide-base-content/25 border-base-content/25 flex-col divide-y border-s pe-0" >
<button type="button" class="flex size-[1.125rem] items-center justify-center" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="flex size-[1.125rem] items-center justify-center" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Horizontally stacked buttons example.
<label class="label-text" for="number-input-horizontally">Quantity:</label>
<div class="input-group max-w-sm" data-input-number>
<input class="input" id="number-input-horizontally" type="text" value="0" data-input-number-input />
<span class="input-group-text divide-base-content/25 border-base-content/25 divide-x border-s pe-0 rtl:divide-x-reverse" >
<button type="button" class="size-9.5 flex items-center justify-center" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="size-9.5 flex items-center justify-center" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Horizontally stretched buttons example.
<label class="label-text" for="number-input-stretched">Quantity:</label>
<div class="input-group max-w-sm" data-input-number>
<span class="input-group-text border-base-content/25 border-e ps-0">
<button type="button" class="size-9.5 flex items-center justify-center" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
</span>
<input class="input" id="number-input-stretched" type="text" value="0" data-input-number-input />
<span class="input-group-text border-base-content/25 border-s pe-0">
<button type="button" class="size-9.5 flex items-center justify-center" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Here’s a simple example: demonstrate setting a maximum width for the main container.
<label class="label-text" for="number-input-mini">Quantity:</label>
<div class="input-group max-w-32" data-input-number>
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
</span>
<input class="input text-center" id="number-input-mini" type="text" value="0" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Here’s an example of a movie ticket booking number counter.
<!-- Number of seat -->
<div class="input-group max-w-xs" data-input-number>
<span class="input-group-text border-base-content/25 border-e ps-0">
<button type="button" class="flex size-12 items-center justify-center" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
</span>
<input class="input pb-0.5 text-center" id="number-input-booking" type="text" value="0" data-input-number-input />
<div class="absolute bottom-1 start-1/2 flex -translate-x-1/2 items-center rtl:translate-x-1/2">
<span class="icon-[tabler--ticket] text-base-content/80 me-2"></span>
<span class="text-xs text-base-content/80 text-nowrap">Number of seat</span>
</div>
<span class="input-group-text border-base-content/25 border-s pe-0">
<button type="button" class="flex size-12 items-center justify-center" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
<!-- Number of Bucket -->
<div class="input-group mt-4 max-w-xs" data-input-number>
<span class="input-group-text border-base-content/25 border-e ps-0">
<button type="button" class="flex size-12 items-center justify-center" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
</span>
<input class="input pb-0.5 text-center" id="number-input-bucket" type="text" value="0" data-input-number-input />
<div class="absolute bottom-1 start-1/2 flex -translate-x-1/2 items-center rtl:translate-x-1/2">
<span class="icon-[tabler--brand-bitbucket] text-base-content/80 me-2"></span>
<span class="text-xs text-base-content/80 text-nowrap">Number of Bucket</span>
</div>
<span class="input-group-text border-base-content/25 border-s pe-0">
<button type="button" class="flex size-12 items-center justify-center" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
Increase or decrease values in steps. This example uses a ":step"
value of 5
.
<div class="input-group max-w-sm" data-input-number='{ "step": 5 }'>
<input class="input" type="text" value="0" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
You can control the minimum value with ":min"
and set the maximum value with ":max"
.
In the example below, the maximum number that can be selected is 15
.
<div class="input-group max-w-sm" data-input-number='{ "max": 15 }'>
<input class="input" type="text" value="15" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
In the example below, the minimum number that can be selected is -15
.
<div class="input-group max-w-sm" data-input-number='{ "min": -15 }'>
<input class="input" type="text" value="-15" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
PARAMETERS | DESCRIPTION | OPTIONS | DEFAULT VALUE |
---|---|---|---|
data-input-number | Activate an Input Number by specifying on an element. | - | - |
data-input-number-input | Applied to the input element. | - | - |
data-input-number-increment | Applied to the increment button. | - | - |
data-input-number-decrement | Applied to the decrement button. | - | - |
:step | Determines the step by which the value will increase or decrease. | number | 1 |
:min | Defines the minimum value that can be entered. Setting it to -Infinity allows unrestricted negative values. | number / “-Infinity” | 0 |
:max | max Defines the maximum possible value. | number / null | null |
The HSInputNumber
object is contained within the global window
object.
METHOD | DESCRIPTION |
---|---|
HSInputNumber.getInstance(target, isInstance) | Returns the element associated to the target .
|
METHOD | DESCRIPTION | RETURNING VALUE |
---|---|---|
on:change | Called when input value is changed. | Current value. |
Assign an ID to the data-input-number
in the events. Increment the number and check the output in the console.
<div class="input-group max-w-sm" data-input-number id="input-number">
<input class="input" type="text" value="1" data-input-number-input />
<span class="input-group-text gap-3">
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-decrement>
<span class="icon-[tabler--minus] size-3.5 flex-shrink-0"></span>
</button>
<button type="button" class="btn btn-primary btn-soft size-[22px] rounded min-h-0 p-0" data-input-number-increment>
<span class="icon-[tabler--plus] size-3.5 flex-shrink-0"></span>
</button>
</span>
</div>
<script>
window.addEventListener('load', function () {
const el = HSInputNumber.getInstance('#input-number')
el.on('change', ({ inputValue }) => {
console.log('Changed to:', inputValue)
})
})
</script>
Open any accordion event example.
const el = HSInputNumber.getInstance('#input-number');
el.on('change', ({inputValue}) => {console.log('Changed to:', inputValue)});