123

Is it possible to apply a style in the inner "up arrow" and "down arrow" of a <input type="number"> in CSS? I would like to change the background of the up arrow to blue and the down arrow to red. Any ideas?

styling inner arrows

LiaVa
  • 198
  • 1
  • 10
Savrige
  • 3,352
  • 3
  • 32
  • 38

12 Answers12

100

The spinners are part of the Shadow DOM. For now, just to hide in Chrome, use:

input[type=number]::-webkit-inner-spin-button {
  -webkit-appearance: none;
}
<input type="number" />

or to always show:

input[type=number]::-webkit-inner-spin-button {
  opacity: 1;
}
<input type="number" />
TylerH
  • 20,799
  • 66
  • 75
  • 101
Alex Char
  • 32,879
  • 9
  • 49
  • 70
  • 1
    Also there are some plugins for this job like kendo: http://demos.telerik.com/kendo-ui/numerictextbox/index – Alex Char Sep 24 '14 at 19:24
  • I notice chrome fade out the spin button when input loses focus. I wonder if there is a rule in css to fix it on screen, making the spin button always visible? – Savrige Sep 24 '14 at 19:34
  • Look at the accepted answer in this thread: http://stackoverflow.com/questions/25194631/is-it-possible-to-always-show-up-down-arrows-for-input-number It worked for me. – Dan Apr 09 '15 at 11:19
  • 1
    I recommend to look at this code example here https://codepen.io/komarovdesign/pen/PPRbgb Its a js + css solution and cross browser compatible (Firefox,Chrome,Safari tested). For the buttons you can add images like .svg, or png. – nh-labs Sep 16 '17 at 20:15
  • 1
    This solution doesn't work in Firefox – Javi Villar Jun 06 '23 at 15:20
58

For Mozilla

input[type=number] { 
    -moz-appearance: textfield;
    appearance: textfield;
    margin: 0; 
}

For Chrome

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button { 
      -webkit-appearance: none; 
      margin: 0; 
}
MDXZ
  • 160
  • 12
saghar.fadaei
  • 3,205
  • 1
  • 17
  • 10
14

I've been struggling with this on mobile and tablet. My solution was to use absolute positioning on the spinners, so I'm just posting it in case it helps anyone else:

<html><head>
    <style>
      body {padding: 10px;margin: 10px}
      input[type=number] {
        /*for absolutely positioning spinners*/
        position: relative; 
        padding: 5px;
        padding-right: 25px;
      }

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

      input[type=number]::-webkit-outer-spin-button, 
      input[type=number]::-webkit-inner-spin-button {
        -webkit-appearance: inner-spin-button !important;
        width: 25px;
        position: absolute;
        top: 0;
        right: 0;
        height: 100%;
      }
    </style>
  <meta name="apple-mobile-web-app-capable" content="yes"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0"/>
  </head>
  <body >
    <input type="number" value="1" step="1" />

  </body></html>
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
JoeP
  • 856
  • 4
  • 15
  • 29
12

I modified @LcSalazar's answer a bit... it's still not perfect because the background of the default buttons can still be seen in both Firefox, Chrome & Opera (not tested in Safari); but clicking on the arrows still works

Notes:

  • Adding pointer-events: none; allows you to click through the overlapping button, but then you can not style the button while hovered.
  • The arrows are visible in Edge, but don't work because Edge doesn't use arrows. It only adds an "x" to clear the input.

.number-wrapper {
  position: relative;
}

.number-wrapper:after,
.number-wrapper:before {
  position: absolute;
  right: 5px;
  width: 1.6em;
  height: .9em;
  font-size: 10px;
  pointer-events: none;
  background: #fff;
}

.number-wrapper:after {
  color: blue;
  content: "\25B2";
  margin-top: 1px;
}

.number-wrapper:before {
  color: red;
  content: "\25BC";
  margin-bottom: 5px;
  bottom: -.5em;
}
<span class='number-wrapper'>
    <input type="number" />
</span>
Mottie
  • 84,355
  • 30
  • 126
  • 241
11

A little different to the other answers, using a similar concept but divs instead of pseudoclasses:

input {
  position: absolute;
  left: 10px;
  top: 10px;
  width: 50px;
  height: 20px;
  padding: 0px;
  font-size: 14pt;
  border: solid 0.5px #000;
  z-index: 1;
}

.spinner-button {
  position: absolute;
  cursor: default;
  z-index: 2;
  background-color: #ccc;
  width: 14.5px;
  text-align: center;
  margin: 0px;
  pointer-events: none;
  height: 10px;
  line-height: 10px;
}

#inc-button {
  left: 46px;
  top: 10.5px;
}

#dec-button {
  left: 46px;
  top: 20.5px;
}
<input type="number" value="0" min="0" max="100"/>
<div id="inc-button" class="spinner-button">+</div>
<div id="dec-button" class="spinner-button">-</div>
Richard Yan
  • 1,276
  • 10
  • 21
6

Crazy idea...

You could play around with some pseudo elements, and create up/down arrows of css content hex codes. The only challange will be to precise the positioning of the arrow, but it may work:

input[type="number"] {
    height: 100px;
}

.number-wrapper {
    position: relative;
}

.number-wrapper:hover:after {
    content: "\25B2";
    position: absolute;
    color: blue;
    left: 100%;
    margin-left: -17px;
    margin-top: 12%;
    font-size: 11px;
}

.number-wrapper:hover:before {
    content: "\25BC";
    position: absolute;
    color: blue;
    left: 100%;
    bottom: 0;
    margin-left: -17px;
    margin-bottom: -14%;
    font-size: 11px;
}
<span class='number-wrapper'>
    <input type="number" />
</span>
LcSalazar
  • 16,524
  • 3
  • 37
  • 69
  • 6
    Really good try @LcSalazar with some issues. It doesn't work when you click exactly on arrow. Also when you mouse out and keep focus show the default one. +1 though :) – Alex Char Sep 24 '14 at 19:39
2

The solution for Firefox is:

input[type=number] { 
  -moz-appearance: textfield;
  appearance: textfield;
  margin: 0; 
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
psanjib
  • 1,255
  • 2
  • 15
  • 24
2

The CSS to modify the spinner arrows is obtuse and unreliable cross-browser.

The most stable option I have found, is to absolutely position an image with pointer-events: none; on top of the spinners.

Works in all modern browsers.

TylerH
  • 20,799
  • 66
  • 75
  • 101
0

Tested in Edge, this works to hide the arrows in Edge...

input[type=number]::-webkit-inner-spin-button, ::-webkit-outer-spin-button{
    opacity: 0;
}
F. Müller
  • 3,969
  • 8
  • 38
  • 49
Niko
  • 1
  • 1
  • 1
    Hi there. If you can, always provide some information about the code you present as the solution (i.e. "the how" and "the why"). It is also nice to back up your statement with links, online documentation like mdn, caniuse or something similar. – F. Müller Sep 25 '21 at 08:09
0

Use the transform-scale CSS option in an input class:

.input-big {  
  transform: scale(2);
  font-size: .5em;
  height: 20.5px;
  padding: 0 0 0 5px;
  margin-left: 2.7em;  
  border-radius: 2px;
}

font-size, height, etc., must be reduced to keep the original view, but now with big arrows.

TylerH
  • 20,799
  • 66
  • 75
  • 101
0

In Chrome I used the filter property.

For example, to have a white background behind the spinners I used this code:

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
    opacity: 1;
    filter: brightness(1.1);
  }
Ale
  • 117
  • 1
  • 13
0

The best way to accomplish this is with a little CSS and jQuery, but there is no pure CSS solution. It's already been stated, but you will need to hide the existing number controls first. Usually this can be accomplished with the CSS appearance property with either a value of none or textfield.

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

Some vendor fixes will be required, but the appearance property will work as is in both Firefox and Chrome.

Once you've done that, you'll need to create some containers that will act as your new number field controls that you can use to absolute position over your number field.

<div class="quantity">
    <input type="number" min="1" max="">
    <div class="quantity-nav">
        <a href="#" class="quantity-button quantity-up">+</a>
        <a href="#" class="quantity-button quantity-down">-</a>
    </div>
</div>

Once you have your containers prepped, simply drop in some jQuery event handlers to control the numbers being output in your input field.

jQuery('.quantity').each(function () {
    var spinner = jQuery(this),
        input = spinner.find('input[type="number"]'),
        btnUp = spinner.find('.quantity-up'),
        btnDown = spinner.find('.quantity-down'),
        min = input.attr('min');

    btnUp.click(function (e) {
        e.preventDefault();
        var oldValue = parseFloat(input.val());
        if (oldValue > 0) {
            var newVal = oldValue + 1;
        } else {
            var newVal = 1;
        }
        spinner.find("input").val(newVal);
        spinner.find("input").trigger("change");
    });

    btnDown.click(function (e) {
        e.preventDefault();
        var oldValue = parseFloat(input.val());
        if (oldValue <= min) {
            var newVal = oldValue;
        } else {
            var newVal = oldValue - 1;
        }
        spinner.find("input").val(newVal);
        spinner.find("input").trigger("change");
    });

});

Once you've confirmed everything is working, you can style your containers in whatever way you see fit.