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?

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?

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" />
input[type=number] {
-moz-appearance: textfield;
appearance: textfield;
margin: 0;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
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>
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:
pointer-events: none; allows you to click through the overlapping button, but then you can not style the button while hovered..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>
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>
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>
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.
Tested in Edge, this works to hide the arrows in Edge...
input[type=number]::-webkit-inner-spin-button, ::-webkit-outer-spin-button{
opacity: 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.
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);
}
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.