Creating stylish number input with custom buttons

Published: · Reading time: 6 min

By default, the appearance of the number input is not very user-friendly, particularly the arrows. In this article, I will demonstrate how you can customize it to make it more appealing and easier to use.


  1. Hide default arrows
  2. Add custom buttons
  3. Styling the input
  4. Demo

Hide default arrows

The default number input arrows are often considered suboptimal because of their unappealing design and limited usability, making them less intuitive and user-friendly for individuals interacting with the input field.

Not to mention the lack of consistency accross different browsers. The arrows will appear on hover.

Number input on Chrome browser
Number input on Chrome
Number input on Firefox browser
Number input on Firefox
Number input on Safari browser
Number input on Safari
Number input on Edge browser
Number input on Edge

To hide the default arrows, you’ll need to use the ::-webkit-outer-spin-button and ::-webkit-inner-spin-button pseuso-elements.

These will only work for the WebKit or Blink based browsers. To hide the arrows on Firefox, you’ll need to use the vendor prefixed appearance property with a value of textfield on the number input.

/* WebKit and Blink */
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;

/* Firefox */
input[type="number"] {
  -moz-appearance: textfield;

Add custom buttons

Now that the default arrows are hidden, we can add buttons that will act as increment and decrement controls for the number input.

Usually, what you will see is the decrement button on the left side of the input and the increment button on the right side of the input. This is how I’m going to do it as well; however, you can position the buttons any way you like.

  title="Decrease value"
  aria-label="Decrease value">-</button>


  title="Increase value"
  aria-label="Increase value">+</button>


For each button, we will include a title attribute to signify the action of the button. Additionally, we will add an aria-label attribute to enhance accessibility for assistive technologies.

The decrease button will feature a “-“ symbol, while the increase button will showcase a “+” symbol.

Finally, the buttons will have an onclick attribute that will modify the number input value. This attribute will reference the id attribute of the number input, which is available in the global scope, along with a corresponding method to either increase (stepUp()) or decrease (stepDown()) the value.

Styling the input

Finally, let’s add some styles to the buttons and input.

I’ll define CSS variables to maintain consistency in properties such as border, border-radius, height and font-size.

In the end, I’ll apply pseudo-classes (focus, hover and active) for an improved UI and enhanced accessibility.

:root {
  --border-radius: 3px;
  --border: 2px solid #3b3b3b;
  --control-size: 38px;
  --font-size: 20px;

.value-control {
  width: var(--control-size);
  height: var(--control-size);
  margin: 0 8px;
  background: transparent;
  border: var(--border);
  border-radius: var(--border-radius);
  color: #3b3b3b;
  cursor: pointer;
  font-size: var(--font-size);

.value-control:hover {
  background: #eee;

.value-control:active {
  background: #ddd;

.value-input:focus {
  outline: 2px solid #3e67fd;
  outline-offset: 1px

.value-input {
  margin: 0;
  height: var(--control-size);
  width: 80px;
  border: var(--border);
  border-radius: var(--border-radius);
  padding: 2px 8px;
  text-align: center;
  font-size: var(--font-size);

.value-input:hover {
  border-color: #777;


The final result will be a more appealing presentation of the numeric value, offering an improved method for users to modify it either through the input itself or the more distinct and larger buttons.

You can find a full demo with a complete code examples on my CodePen:

See the Pen Custom number input by Nikita Hlopov (@nikitahl) on CodePen.

Like this article? Share it on: