4

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?

Martin
  • 22,212
  • 11
  • 70
  • 132
  • At some point it's hard and tricky to get a consistent result across the platforms for a native element like `input`. Why not just recreate it by using some `button` like [this example](https://codepen.io/bbbenji/pen/XGoWNW)? – johannchopin Apr 16 '21 at 18:30
  • @johannchopin yes I'd hoped to avoid adding a layer of JS on to the system but this does seem to work and I think I will begrudgingly have to conceed that JS is the way to resolve this. Feel free to stick the code in an answer `;-)` – Martin Apr 17 '21 at 09:53

3 Answers3

6

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>
johannchopin
  • 13,720
  • 10
  • 55
  • 101
  • This works, but on non-ipad styling this produces two sets of arrows – Martin Apr 17 '21 at 20:00
  • Ideally I would be looking for something with [-][number][+] styling, but if it has to be JS then I'm sure there are plenty of options for me to explore. My question was really about if this uniformity was possible with native CSS – Martin Apr 17 '21 at 20:02
  • 1
    @Martin I added a custom example with the `[-][number][+]` design ;) The js script part still the same. – johannchopin Apr 18 '21 at 08:54
  • @Martin Does this answer looks good to maybe be validated? :) – johannchopin Apr 20 '21 at 09:53
  • 1
    Hello, yes, I had a quick look at this the other day and it does look promising but I've not been able to get back to this project yet, but I will be back on it in a day or two and will tidy up this loose end, thanks again for your help `:-)` – Martin Apr 20 '21 at 10:38
  • Hi Johannchopin, I am finally on looking at this in detail. Would it be possible to clarify the answer with JQuery rather than javascript as that's used elsewhere in this project. Thank you. `:-)` – Martin Apr 22 '21 at 08:56
  • @Martin I added an example ;) – johannchopin Apr 23 '21 at 10:17
  • Ah I thought that the jQuery would add another interface level. That's great. Cheers – Martin Apr 23 '21 at 10:20
2

I have been looking for so long to show arrows on Mobile Chrome when I realized that the operating system deals differently with inputs (popping up the keyboard and not showing arrows). I came across this post and I have improved the code to make that you can have many buttons in the same page but just one function to manage the increment/decrement of each. The final example is like in the picture below for smartphones.

To add a third button just make the input with id='3' and the button with plus sign with id='pb3' and the button with minus side with id='mb3' You do not need to change anything else

You can either use the onchange event or the onkeyup event to call imposeMinMax() function. Depending on your application. onkeyup works well only if you have a min<0 and max>0.

I have also added autoincrement input when the user keeps the button pressed. Visit this link for the autoincrement code.

enter image description here

function imposeMinMax(el){ /*this function delimits max and min*/
  if(el.value != ""){
    if(parseInt(el.value) < parseInt(el.min)){
      el.value = el.min;
    }
    if(parseInt(el.value) > parseInt(el.max)){
      el.value = el.max;
    }
  }
}

function modIn(inId){
  if(inId.charAt(0)=='p'){                  /*p for plus*/
    var targetId = inId.match(/\d+/)[0];    /*just keep the number*/
    document.getElementById(targetId).value ++;
    imposeMinMax(document.getElementById(targetId));
  } 
  if(inId.charAt(0)=='m'){                  /*m for minus*/
    var targetId = inId.match(/\d+/)[0];
    document.getElementById(targetId).value --;
    imposeMinMax(document.getElementById(targetId));
  } 
}
.signBut {
      width: 30px;
      margin-bottom: 5px;
    }

.inNum {width: 40px;}
  
<!--    Bootstrap --> 
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

<div class='card'>
  <div class='card-body' >
    <h5 class='card-title'>TEMPERATURE</h5>
      <div class='container'>
        <div class='row'>
          <div class='col-auto' style="width: 40%;">
            <label >Temprerature:</label>
          </div>
          <div class='col-auto'>
            <button type="button" class="btn btn-danger btn-sm signBut" id='mb1' onclick='modIn(this.id)'>-</button>
            <input type="number" name='tempCalib' id='1' class='inNum' onchange='imposeMinMax(this)' value='0' max='6' min="-6" step="1">                 
            <button type="button" class="btn btn-danger btn-sm signBut" id='pb1' onclick='modIn(this.id)'>+   </button>&nbsp;°C
          </div>
        </div>
        <br>
        <div class='row'>
          <div class='col-auto' style="width: 40%;">
            <label>Hysteresis:</label>
          </div>
          <div class='col-auto'>
            <button type="button" class="btn btn-danger btn-sm signBut" id='mb2' onclick='modIn(this.id)'>-</button>
            <input type="number" name='tempHyst' id='2' class='inNum' onchange='imposeMinMax(this)' value="1" max="4" min="-4" step="1">                 
            <button type="button" class="btn btn-danger btn-sm signBut" id='pb2' onclick='modIn(this.id)'>+</button>&nbsp;°C
          </div>
         </div>
        </div>
       </div>
      </div>
Pietro
  • 127
  • 6
  • This looks like it could be exactly what I'm looking for, When I'm back on that project I will try out your code. Thank you. – Martin Aug 06 '21 at 10:08
  • 1
    Yes basically the good thing is that you can add as many buttons and inputs as you like. – Pietro Aug 06 '21 at 10:11
-1

You can try to check this example here for this

shark
  • 27
  • 6
  • Thanks, but this doesn't solve the issue. I have updated the question accordingly. – Martin Apr 17 '21 at 09:51
  • Then this answer might help you based on the updated question you have https://stackoverflow.com/a/51747587/8461587 – shark Apr 17 '21 at 10:30