Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

shahr's avatar
Level 10

Customize Increment Arrows on Input of Type Number Using CSS

I have a psd like this. And I would like to turn it into something like this:

psd

html

<td>
    <div class="form-row justify-content-center">
        <div class="form-group">
            <div class="input-group mx-auto mb-3">
                <div class="number-input">
                    <button onclick="this.parentNode.querySelector('input[type=number]').stepDown()" ></button>
                    <input class="quantity" min="0" placeholder="0" name="quantity" value="1" type="number">
                    <button onclick="this.parentNode.querySelector('input[type=number]').stepUp()" class="plus"></button>
                </div>
            </div>
        </div>
    </div>
</td>

css

input[type="number"] {
    -webkit-appearance: textfield;
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
    -webkit-appearance: none;
}

.number-input {
    border: 2px solid #ddd;
    display: inline-flex;
}

.number-input,
.number-input * {
    box-sizing: border-box;
}

.number-input button {
    outline:none;
    -webkit-appearance: none;
    background-color: transparent;
    border: none;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    cursor: pointer;
    margin: 0;
    position: relative;
}

.number-input button:before,
.number-input button:after {
    display: inline-block;
    position: absolute;
    content: '';
    width: 1rem;
    height: 2px;
    background-color: #212121;
    transform: translate(-50%, -50%);
}
.number-input button.plus:after {
    transform: translate(-50%, -50%) rotate(90deg);
}

.number-input input[type=number] {
    font-family: sans-serif;
    max-width: 5rem;
    padding: .5rem;
    border: solid #ddd;
    border-width: 0 2px;
    text-align: center;
}

But I see this demo

demo

It show very bad.

The second view is emulated using two separate buttons.

How could I style the arrows as described?

Could anyone please suggest where I am going wrong?

Thanks.

0 likes
3 replies
Tray2's avatar

It's always tricky to style forms elements and the number element is not properly supported by all browsers yet. So I woul most likely create a text field surrounded by two buttons and handle it with some javascript. Then I can style each element on it's own.

Something like this

<div>
  <button onclick="dec()">-</button>
  <input name="number" type="text" readonly value="0">
  <button onclick="inc()">+</button>  
</div>
function inc() {
  let number = document.querySelector('[name="number"]');
  number.value = parseInt(number.value) + 1;
}

function dec() {
  let number = document.querySelector('[name="number"]');
	if (parseInt(number.value) > 0) {
	  number.value = parseInt(number.value) - 1;
  }
}
Tray2's avatar
Tray2
Best Answer
Level 73

When you have more than one you need pass the element in question otherwise it will just use the one I hardcoded in.

let number = document.querySelector('[name="number"]');

You can do something like this

<div>
  <button onclick="dec('qty')">-</button>
  <input name="qty" type="text" readonly value="0">
  <button onclick="inc('qty')">+</button>  
</div>

<div>
  <button onclick="dec('amount')">-</button>
  <input name="amount" type="text" readonly value="0">
  <button onclick="inc('amount')">+</button>  
</div>
function inc(element) {
  let el = document.querySelector(`[name="${element}"]`);
  el.value = parseInt(el.value) + 1;
}

function dec(element) {
  let el = document.querySelector(`[name="${element}"]`);
	if (parseInt(el.value) > 0) {
	  el.value = parseInt(el.value) - 1;
  }
}

Check this fiddle

https://jsfiddle.net/62bxcd43/

You can add some more code to handle the range quite easily.

1 like

Please or to participate in this conversation.