Styled cross-platform number input (in Angular but applicable to any HTML/CSS app)

Native elements in HTML 5 such as the number input are great, but unfortunately our designers often want them to render the same between different browsers and operating systems. For example on linux/chrome the number input has an up/down spinner on the right hand side which is always visible. On Mac the spinner is only visible on mouse over, on firefox it is rendered differently and on mobile the spinner is not there at all usually. In this case, my designer wanted number input with up/down buttons always available. This was for an order quantity input, so it should be integers from 1 upwards. With bootstrap you can easily add buttons etc to the left or right of an input, however I couldn’t see an easy way in ‘native’ bootstrap to have two buttons stacked as one of the addons, so I created my own html/less. This is for Angular 1, bootstrap 3 and fontawesome but it should be very easy to change for different platforms.

Here’s the HTML

<div class="number-input-group">
    <input class="noscroll" type="number" min=1 max=100 step=1 ng-model="extra.quantity"/>
    <div class="buttons">
        <div ng-click="extra.quantity = extra.quantity + 1"><i class="fa fa-caret-up"></i></div>
        <div ng-click="extra.quantity = extra.quantity > 1 ? extra.quantity - 1 : extra.quantity"><i class="fa fa-caret-down"></i></div>

And the LESS:

.number-input-group {
    display: table; 
    width: 100%;    // fill container - remove if you want it as effectively an inline-block
    position: relative;
    border-collapse: separate;
    border-spacing: 0px;    
    > input[type=number] {  
        display: table-cell;
        width: 100%; // keep biggest
        border-right: none;         
        &::-webkit-inner-spin-button, &::-webkit-outer-spin-button {
            -webkit-appearance: none;   
            margin: 0;                  
    > .buttons {            
        display: table-cell;
        width: 1%;      // shrink to smallest size
        vertical-align: top;
        border: @input-transparent-border-width solid @bespoke-light-black;
        //color: @bespoke-light-black;
        > div { 
            @number-input-group-arrow-box-size: (@input-padding-top * 2 + @input-line-height - @input-transparent-border-width - 1) / 2;
            line-height: @number-input-group-arrow-box-size * 0.8;  // make a bit smaller because ff and chrome mobile add a few px for some reason
            font-size: @number-input-group-arrow-box-size * 1;
            padding: 0 7px;
            &:hover {
                background-color: lighten(@background-color, 15%);

            &:last-child {
                border-top: @input-transparent-border-width solid @bespoke-light-black;

Leave a Reply

Your email address will not be published. Required fields are marked *