Search code examples
htmlcssipadspinner

How to always display numerical input spinners on mobile and iPad


I have some HTML/CSS that works perfectly on desktop.

It also works on mobile, but the up and down arrows for numerical selection on the input field do not display, forcing the user to "enter" the number manually. The client has requested these numerical spinner arrows are retained on mobile view.

There are a lot of questions about how to hide/disable spinners and even a few about how to retain the spinners, but these have no or incorrect answers and following these answers and suggestions has not resolved this issue.

        @media only screen {

            input[type=number] {
               /* -moz-appearance: number-input; */   
            }
 
            input[type=number]::-webkit-inner-spin-button,
            input[type=number]::-webkit-outer-spin-button {
                -webkit-appearance: inner-spin-button;
                /***
                 * Below tried and failed: 
                 ***/
                /* -moz-appearance: number-input; */ 
                /*-ms-appearance: inner-spin-button;*/
                /*appearance: auto;*/
                margin: 0;
                opacity: 1;
            }
            
            #updQtyLoose47 {
             /* basic styling */
            background: rgba(245, 235, 170, 0.75);
            border-radius: 0;
            border: none;
            border: solid 1px #dbdbdb;
            color: inherit;
            display: block;
            outline: 0;
            padding: 0.25rem 0 0.25rem 0.75rem;
            text-decoration: none;
            width: 100px;
            }
        }
<div>
<input type="number" name="Quantity[47]" value="0" class="qtyInputLoose" id="updQtyLoose47" min="0" max="8" >
</div>

Platform:

iPad (iOS 12.5)

Browsers:

Google Chrome and Safari

Attempted solutions:

  • opacity is set to 1 but this does not display the spinners (source).
  • Setting moz-appearance: number-input; (and similar) doesn't display the spinners (source).
  • Setting -webkit-appearance: inner-spin-button; doesn't display the spinners (source).
  • Setting inputmode="numeric" on the HTML input element does not show spinners (source).

iPad simulators (for what they're worth) on PC on Firefox Inspector shows the spinner buttons, and Google Chrome Inspector they do NOT show the spinner buttons.

There is a comment here that

In firefox and safari, its a default feature to show it always.

This no longer appears to be the case for Safari 12.1

How can I show these input spinner buttons on iPad display of the webpage?


Solution

  • At some point it's hard and tricky to get a consistent result across the platforms for a native element like an input. For this reason, I would recommend you to re-create one that 'fake' the native behaviour by using some javascript. Here is a very basic example:

    const input = document.querySelector('input[type=number]')
    
    const increment = () => {
      input.value = Number(input.value) + 1
    }
    const decrement = () => {
      input.value = Number(input.value) - 1
    }
    
    document.querySelector('.spinner.increment').addEventListener('click', increment)
    document.querySelector('.spinner.decrement').addEventListener('click', decrement)
    input[type=number]::-webkit-inner-spin-button,
    input[type=number]::-webkit-outer-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
    
    .number-input {
      position: relative;
      width: fit-content;
    }
    
    input {
      width: 60px;
    }
    
    .spinners {
      position: absolute;
      right: 0;
      top: 50%;
      display: flex;
      flex-direction: column;
      width: fit-content;
      margin: 1px;
      transform: translateY(-50%);
    }
    
    .spinner {
      font-size: 7px;
      border: none;
      padding: 0 1px;
    }
    
    .spinner:hover {
      background: lightgrey;
    }
    <div class="number-input">
      <input type="number" name="Quantity[47]" value="0" class="qtyInputLoose" min="0" max="8">
      <div class="spinners">
        <button class="spinner increment">&#9650;</button>
        <button class="spinner decrement">&#9660;</button>
      </div>
    </div>

    If you need something more customised, simply adjust a little bit of css and html structure:

    const input = document.querySelector('input[type=number]')
    
    const increment = () => {
      input.value = Number(input.value) + 1
    }
    const decrement = () => {
      input.value = Number(input.value) - 1
    }
    
    document.querySelector('.spinner.increment').addEventListener('click', increment)
    document.querySelector('.spinner.decrement').addEventListener('click', decrement)
    input[type=number]::-webkit-inner-spin-button,
    input[type=number]::-webkit-outer-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
    
    .number-input {
      display: flex;
    }
    
    input {
      width: 40px;
      border: solid 1px lightgrey;
      border-radius: 0;
      text-align: center
    }
    
    .spinner {
      border: solid 1px lightgrey;
    }
    
    .spinner:hover {
      background: lightgrey;
    }
    
    .spinner:first-child {
      border-radius: 3px 0 0 3px;
    }
    
    .spinner:last-child {
      border-radius: 0 3px 3px 0;
    }
    <div class="number-input">
      <button class="spinner decrement">-</button>
      <input type="number" name="Quantity[47]" value="0" class="qtyInputLoose" min="0" max="8">
      <button class="spinner increment">+</button>
    </div>

    Here is a version with JQuery:

    const input = $('input[type=number]')
    
    const increment = () => {
      input.val(Number(input.val()) + 1)
    }
    const decrement = () => {
      input.val(Number(input.val()) - 1)
    }
    
    $('.spinner.increment').click(increment)
    $('.spinner.decrement').click(decrement)
    input[type=number]::-webkit-inner-spin-button,
    input[type=number]::-webkit-outer-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
    
    .number-input {
      display: flex;
    }
    
    input {
      width: 40px;
      border: solid 1px lightgrey;
      border-radius: 0;
      text-align: center
    }
    
    .spinner {
      border: solid 1px lightgrey;
    }
    
    .spinner:hover {
      background: lightgrey;
    }
    
    .spinner:first-child {
      border-radius: 3px 0 0 3px;
    }
    
    .spinner:last-child {
      border-radius: 0 3px 3px 0;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    
    <div class="number-input">
      <button class="spinner decrement">-</button>
      <input type="number" name="Quantity[47]" value="0" class="qtyInputLoose" min="0" max="8">
      <button class="spinner increment">+</button>
    </div>