Prevent arrow keys from changing values in a number input
Asked Answered
G

8

26

I have an input control on a webpage similar to this:

<input type="number" name="value" />

If this control has focus and I hit either the up or down arrow keys, then the value in the textbox increments or decrements (except in IE).

I would like to disable this feature, preferably using CSS. I already have the spinner buttons removed using CSS. I realize I could use JavaScript to capture the keydown event, but I want to allow the arrow keys to continue to scroll the page up or down.

Garget answered 12/6, 2014 at 19:20 Comment(6)
Why are you using input type="number" when you don’t want its basic functionality?Scholz
Partial duplicate: #23373403Scholz
add step=0 and you should be okCotenant
Thanks Jukka, using type="text" worked easily enough. Sorry Rachel, that didn't do it, at least not in FirefoxGarget
Arrow keys scroll the page up and down only when the page itself is focused on. When an input has the focus, the page scroll doesn't work with arrows anyway.Drabeck
@RachelGallen add step=0 and you should be ok doesn't work unfortunatelyHilleary
N
37

There is no way of doing the behavior you are describing purely with CSS because CSS handles display and we are talking about behavior and keyboard events here.

I would suggest to add an event listener to your input which will prevent the arrow keys from having an effect on it witout actually preventing the page scroll with the input is not in focus:

document.getElementById('yourInputID').addEventListener('keydown', function(e) {
    if (e.which === 38 || e.which === 40) {
        e.preventDefault();
    }
});

If by any chance you want the arrow keys to scroll the page event if the input is in focus, I would suggest using JQuery which will allow you to write less code and it will support all browsers.

Northwesterly answered 19/10, 2017 at 11:14 Comment(0)
A
6

You can use the below code (JSFiddle):

$(document).ready(function() {
  $("input[type=number]").on("focus", function() {
    $(this).on("keydown", function(event) {
      if (event.keyCode === 38 || event.keyCode === 40) {
        event.preventDefault();
      }
    });
  });
});
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" min="1.01" max="1000" id="num" />
Adallard answered 23/10, 2017 at 18:56 Comment(0)
L
6

If you are using Angular, try:

<input type="number"onwheel="return false;" (keydown.arrowup)="(false) (keydown.arrowdown)="(false)"/>
Lansquenet answered 25/2, 2021 at 17:56 Comment(0)
R
2

I know this isn't the answer you want to hear but is this something you should really be doing?

Just because, in this instance, it does not suit you, you appear to be going against expected behaviour from the browser and user to try and manipulate something into doing something it doesn't.

As a user, tabbing into a field and being able to use the up and down arrows to alter the value is the expected behaviour. Such as clicking a logo takes you home, or pressing Cmd/Ctrl + W closes the window. If anything interferes with this, you are ultimately going to alienate the user and they are going to lose faith in your interface.

Even with a standard type="text" box, the up and down arrows don't scroll the page, this functionality seems to go against everything that is standard.

Saying that you've given no context for this issue and it could be for an internal tool or private use, in which case, JS looks like the way to go!

Ratepayer answered 19/10, 2017 at 10:48 Comment(0)
A
1

as you can see in this article you can use this CSS depends on browser that you used

    /* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Firefox */
input[type=number] {
  -moz-appearance: textfield;
}
<input type="number">
Angary answered 25/9, 2021 at 8:42 Comment(0)
T
0

If you are using Angular you can create a custom directive that does the job:

ng generate directive DisableArrowUpDownWheel

This is the code for the directive:

import { Directive, ElementRef } from '@angular/core';   
@Directive({
  selector: '[disableArrowUpDownWheel]',
})
export class DisableArrowUpDownWheelDirective {
  constructor(private el: ElementRef) {
    let input: HTMLInputElement = el.nativeElement;
    // disable the scroll wheel
    input.onwheel = () => {
      return false;
    };
    // disable the up/down arrow keys
    input.onkeydown = (event: KeyboardEvent) => {
      if (event.key === 'ArrowDown' || event.key === 'ArrowUp') return false;
      else return true;
    };
  }
}

See https://angular.io/guide/attribute-directives for more info about custom directives.

Tampere answered 3/6, 2022 at 13:51 Comment(0)
P
-3

Oh, I was just able to do it with a keydown listener and the following filter:

const invalid = ['e', ',', '.', 'ArrowUp', 'ArrowDown'];
if (invalid.find(e => $event.key === e)) {
  $event.preventDefault();
}

In my case, I also want to forbid the chars: e , .

Pyszka answered 19/10, 2017 at 10:25 Comment(0)
B
-3
<input type = "number" inputmode = "numeric">
Boart answered 24/6, 2023 at 14:27 Comment(1)
Answer needs supporting information Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Tailrace

© 2022 - 2024 — McMap. All rights reserved.