350

I'm using the jQuery Tools Validator which implements HTML5 validations through jQuery.

It's been working great so far except for one thing. In the HTML5 specification, the input type "number" can have both integers and floating-point numbers.

This seems incredibly short-sighted since it will only be a useful validator when your database fields are signed floating-point numbers (for unsigned ints you'll have to fall back to pattern validation and thus lose extra features like the up and down arrows for browsers that support it).

Is there another input type or perhaps an attribute that would restrict the input to just unsigned integers?

I couldn't find any.


Setting the step to 1 is not the answer since it doesn't restrict the input. You can still type a negative floating-point number into the textbox.

Also, I am aware of pattern validation (I mentioned it in my original post), but that was not part of the question.

I wanted to know if HTML5 allowed restricting an input of type "number" to positive integer values. To this question the answer, it seems, would be "no, it does not".

I didn't want to use pattern validation because this causes some drawbacks when using jQuery Tools validation, but it now seems that the specification doesn't allow for a cleaner way to do this.

E_net4
  • 27,810
  • 13
  • 101
  • 139
JayPea
  • 9,551
  • 7
  • 44
  • 65
  • 3
    As of 2019—I don't know since when—the `number` input (in FF/Chrome/Safari at least) now only accepts integers by default, _unless_ you set an explicit value for the `step` attr that allows decimal values; e.g: `step="0.01"`. [Documented MDN here](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#step). In two minds about this because I think it's a sensible default, but also a breaking change (yes, it has affected some code I wrote). – Darragh Enright Jan 29 '19 at 19:37
  • 2
    @DarraghEnright Chrome 87 allows non integers to be entered when `step="1"`. MDN says the behavior is up to the browser. – dlsso Jan 22 '21 at 23:53

24 Answers24

392

The best you can achieve with HTML only (documentation):

<input type="number" min="0" step="1"/>
Mmmh mmh
  • 5,334
  • 3
  • 21
  • 29
  • 9
    You should probably set `min` to `1` as he wants positive numbers (and not non-negative numbers). – Martin Thoma May 15 '14 at 20:20
  • 1
    @pwdst I'll second that. `` is the most correct answer to the question. Anyway, what's the point in having both `step="1"` and `pattern="\d+"`? I can't type in floating point numbers in either cases. – Danish Ashfaq Aug 26 '14 at 12:43
  • @pwdst @DanishAshfaq If this pattern attribute is not in the specification for `type="number"` then this answer is wrong. Anyway, it looks like the standard `` is working better than before in Chrome and Firefox. Should I remove the pattern thing? – Mmmh mmh Aug 26 '14 at 13:54
  • 1
    I've tested it in Chrome and Firefox, and there is no need for a pattern attribute. In Chrome, without using the pattern attribute, if I type in "4.23", it even gives me a hint: "Please enter a correct value. The closest ones are 4 and 5." But when using the pattern attribute, it just says "Please enter a correct value." So I guess you could update your answer :) – Danish Ashfaq Aug 28 '14 at 09:21
  • 66
    This did not worked for me on latest version of chrome. It does not allow letters to be typed, but it does allow special characters to be inserted. – Malavos Feb 21 '15 at 21:39
  • 7
    Why I can type e in – grant sun Dec 13 '18 at 19:02
  • 8
    @grantsun for exponential numbers e.g. 10e20. – sn3ll Jan 19 '19 at 23:09
  • 6
    This is not right if you want to "restrict the input to just unsigned integers". The "step" attribute will control the increment/decrement of the input value using the keyboard arrows. It will not prevent decimal input values. – iusting Aug 26 '20 at 15:51
  • 1
    This _is_ the correct answer, but if you want to get the correct integer output from this input, you have to use the DOM API appropriately. First, validate: `input.checkValidity()`. If this returns `false`, then you don’t have an integer, so reject this. Then, get the value as a number: `input.valueAsNumber`. Note that an empty input will be treated as valid, because this input field is optional. If you don’t want that, add the `required` attribute. – Sebastian Simon Dec 03 '22 at 19:58
225

Set the step attribute to 1:

<input type="number" step="1" />

This seems a bit buggy in Chrome right now so it might not be the best solution at the moment.

A better solution is to use the pattern attribute, that uses a regular expression to match the input:

<input type="text" pattern="\d*" />

\d is the regular expression for a number, * means that it accepts more than one of them.

enzo
  • 9,861
  • 3
  • 15
  • 38
js-coder
  • 8,134
  • 9
  • 42
  • 59
  • 1
    On Chrome 18, running Ubuntu, the fiddle above does not seem to work. The number attribute does, however. – Zut May 18 '12 at 09:34
  • 1
    @Zut Works for me. (Chrome 18 and Ubuntu.) Did you actually enter something into the input? Use `` if you don't want to accept an empty input. – js-coder May 18 '12 at 10:17
  • Correction: I'm using Chromium, and not Chrome. I don't suppose it should change anything though. I can type any arbitrary character in the input field. I just double checked, and have now successfully typed "asdf123,.-". – Zut Jul 19 '12 at 18:11
  • 14
    @Zut HTML5 validation doesn't stop you from entering those keys. It just prevents the form from being send with those characters. If you submit a form with an input of the type `number` that contains other characters, then Chrome will show you an error message. – js-coder Jul 19 '12 at 18:42
  • 2
    @dotweb - I see your point. The difference between the two is that with the number attribute, all alphabetic characters are automatically removed when I deselect (trigger blur) for the input. This does not happen when using the pattern attribute. I guess this distinction is only important if you are using AJAX to post your data, and you're using some other event than `submit` to trigger the post. – Zut Jul 20 '12 at 06:57
  • 1
    How is this preventing entering negative numbers? Isn't 'unsigned integers' mean no negatives? – user3285954 Jan 24 '15 at 14:44
  • You can combine the two: – Leths Jul 01 '15 at 12:35
  • if i use pattern like pattern="\d{3,4}" and then want to restrict user to min value 500 and max value 1500, so what to do? – Imran Qamer Dec 15 '15 at 06:34
  • To allow negative numbers, use a pattern like `-?\d*` – mindplay.dk Apr 18 '16 at 13:51
  • 1
    Its still buggy in chrome – SuperUberDuper Oct 30 '17 at 16:48
  • 19
    This does not do what OP asked. **Only integers** `/\d*/.test(1.1) // true` – vsync Jul 11 '18 at 10:27
  • 4
    @vsync `pattern="\d*"` is not the same as `/\d*/`, `pattern="\d*"` is equal to `/^(?:\d*)$/`, please refer to [HTML5 *pattern* attribute documentation](https://www.w3.org/TR/2011/WD-html5-20110525/common-input-element-attributes.html#the-pattern-attribute). – Wiktor Stribiżew Sep 02 '19 at 08:56
  • 2
    Does not work. Upvoted this. Then tested in my project. And now can not downwote:( – Viacheslav Dobromyslov Feb 03 '21 at 08:42
46
<input type="text" name="PhoneNumber" pattern="[0-9]{10}" title="Phone number">

Using this code, the input to the text field limits to enter only digits. Pattern is the new attribute available in HTML 5.

Pattern attribute doc

Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
thejustv
  • 2,009
  • 26
  • 42
  • 17
    According to [the specification](http://www.w3.org/TR/html5/forms.html#the-input-element) the **pattern attribute** can only be used where the input type is Text, Search, URL, Telephone, E-mail, Password (as shown here with the "Text" type). This means that semantics of the number input type and therefore (importantly) the numeric on-screen keyboards of some tablets and phones is lost when using this method. – pwdst Jun 27 '14 at 14:00
  • 3
    This on firefox 36.0 allows you to type letters and special characters. – Malavos Feb 27 '15 at 16:16
  • 4
    It doesn't limit input to numbers only, you can still type letters! – Ali Celebi Nov 15 '19 at 11:17
45

The easy way using JavaScript:

<input type="text" oninput="this.value = this.value.replace(/[^0-9.]/g, ''); this.value = this.value.replace(/(\..*)\./g, '$1');" >
Tarek Kalaji
  • 2,149
  • 27
  • 30
  • I dont understand `replace(/(\..*)\./g, '$1')` – codyc4321 Jan 28 '17 at 14:33
  • 3
    This is important to accept float numbers and repeat `.` only once, e.g. `123.556` can be writen. – Tarek Kalaji Jan 28 '17 at 15:54
  • 16
    @TarekKalaji - questions states **integers** and not **float numbers** – vsync Jul 11 '18 at 10:29
  • 1
    how about mobile device? because type text display all keyboards (alfanumeric chars also) – Nuri YILMAZ Aug 05 '18 at 22:12
  • 1
    Inline event handlers like `oninput` are [bad practice](/q/11737873/4642212). They’re an [obsolete, cumbersome, and unintuitive](/a/43459991/4642212) way to listen for events. Always [use `addEventListener`](//developer.mozilla.org/en/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. Please _never_ suggest or encourage these attributes. The last browser that still needs them reached end of life nearly two decades ago. – Sebastian Simon Dec 03 '22 at 20:19
43

Pattern is nice but if you want to restrict the input to numbers only with type="text", you can use oninput and a regex as below:

<input type="text" oninput="this.value=this.value.replace(/[^0-9]/g,'');" id="myId"/>

I warks for me :)

Viktor Karpyuk
  • 725
  • 7
  • 4
  • 1
    Beware that this approach might negate your (change) method (event handler) and also erase your default value in the input box. – Ali Celebi Nov 15 '19 at 11:22
  • Inline event handlers like `oninput` are [bad practice](/q/11737873/4642212). They’re an [obsolete, cumbersome, and unintuitive](/a/43459991/4642212) way to listen for events. Always [use `addEventListener`](//developer.mozilla.org/en/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. Please _never_ suggest or encourage these attributes. The last browser that still needs them reached end of life nearly two decades ago. – Sebastian Simon Dec 03 '22 at 20:18
42

<input type="number" oninput="this.value = Math.round(this.value);"/>
R. Yaghoobi
  • 459
  • 4
  • 5
  • 4
    Bro, this solution is key! Thank you! – NoWar Sep 01 '20 at 05:58
  • 2
    Inline event handlers like `oninput` are [bad practice](/q/11737873/4642212). They’re an [obsolete, cumbersome, and unintuitive](/a/43459991/4642212) way to listen for events. Always [use `addEventListener`](//developer.mozilla.org/en/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. Please _never_ suggest or encourage these attributes. The last browser that still needs them reached end of life nearly two decades ago. Also, this erases the value and replaces it with `0` on every invalid input. Bad usability. – Sebastian Simon Dec 03 '22 at 20:17
21

This is not only for HTML5. This works fine in all browsers. Try this:

document.getElementById("input").addEventListener("keyup", function() {
  this.value = this.value.replace(/[^0-9]/g, "");
});
<input id="input" type="text">
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
karthick
  • 9
  • 1
  • 2
13

Pattern are always preferable for restriction, try oninput and min occur 1 for inputting only numbers from 1 onwards

<input type="text" min="1" oninput="this.value=this.value.replace(/[^0-9]/g,'');"
                                value=${var} >
dippas
  • 58,591
  • 15
  • 114
  • 126
Noothan y v
  • 159
  • 1
  • 4
  • It is very instresting solution. What for ` value=${var}` is? – NoWar Sep 14 '18 at 08:43
  • @AcademyofProgrammer example default value for that input – Shinigamae Nov 02 '18 at 07:40
  • best answer! works for pasting, works even in IE (10+), gives you the freedom to display any keyboard via the input's type, and does not make chrome display these pesky up/down arrows inside the field. – jaynetics Aug 12 '19 at 09:52
12

Shortest

This is size improvement of R. Yaghoobi answer

<input type="number" oninput="this.value|=0"/>

We use here standard shorthand for "OR" operator e.g 9 | 2 = 11 in binary: 0b1001 | 0b1010 = 0b1011 . This operator first cast numbers to integers in implicit way and then do OR. But because OR with zero don't change anything so number is cast to integer. OR with non-number string gives 0.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
  • Kielczewski Which operator is this? – Niyas Nazar Nov 04 '20 at 08:49
  • 2
    Outstanding! Good job! Thanks! – RicardoPHP Feb 09 '21 at 12:36
  • 1
    This is by far the best answer. Not only deals with the problem in a short, simple way; it also deals with localization issues (e.g. 100,5 vs 100.5 depending on what country you're from) which most other answers don't. – Matias N Goldberg Mar 02 '21 at 15:47
  • you can add a dot – Aamir Afridi Sep 10 '21 at 09:56
  • 3
    the only problem with this solution is that it moves the caret in the beginning after the user tries to enter an invalid character a.k.a. decimal point or letter, etc. – Alexander Mihailov Aug 16 '22 at 10:30
  • Inline event handlers like `oninput` are [bad practice](/q/11737873/4642212). They’re an [obsolete, cumbersome, and unintuitive](/a/43459991/4642212) way to listen for events. Always [use `addEventListener`](//developer.mozilla.org/en/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. Please _never_ suggest or encourage these attributes. The last browser that still needs them reached end of life nearly two decades ago. – Sebastian Simon Dec 03 '22 at 20:05
8

Just putting it in your input field : onkeypress='return event.charCode >= 48 && event.charCode <= 57'

illeas
  • 300
  • 3
  • 18
  • 1
    Maybe you have other problems. – illeas Mar 06 '21 at 14:43
  • No. Your proposal does not handle case when I just paste value to the field. It handles only case when I enter value digit by digit. – Viacheslav Dobromyslov Mar 07 '21 at 17:04
  • Inline event handlers like `onkeypress` are [bad practice](/q/11737873/4642212). They’re an [obsolete, cumbersome, and unintuitive](/a/43459991/4642212) way to listen for events. Always [use `addEventListener`](//developer.mozilla.org/en/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. Please _never_ suggest or encourage these attributes. The last browser that still needs them reached end of life nearly two decades ago. – Sebastian Simon Dec 03 '22 at 20:03
  • 1
    The global [`event`](//developer.mozilla.org/en/docs/Web/API/Window/event) and the [`keypress` event](//developer.mozilla.org/en/docs/Web/API/Element/keypress_event) are deprecated. – Sebastian Simon Dec 03 '22 at 20:04
  • Nice this is best solution , good old return false. This answer gives no blinking solution, perfect prevent ! `addEventListener('keydown', (e) => { if(e.key == "Backspace") { // pass } else { e.preventDefault() return false; } })` this also gives no blink solution and laso allow manipulate with keyCode – Nikola Lukic Sep 01 '23 at 11:19
5

This is an old question, but the accessible (and now supported in most browsers) version would be:

<input type="text" inputmode="numeric" pattern="[0-9]*">

See https://technology.blog.gov.uk/2020/02/24/why-the-gov-uk-design-system-team-changed-the-input-type-for-numbers/

deltragon
  • 555
  • 5
  • 14
  • The pattern you have used only allows integers between 0 and 9. It doesn't allow negatives or values greater than 9 – Ted Mar 31 '22 at 07:02
  • 2
    @Ted The * in the pattern means 0 or more repetitions, meaning eg. 10 or 2134 are also allowed. Additionally, the question specifically asks for unsigned numbers, ie. no negatives - if you want to allow negative numbers the pattern would be `pattern="-?[0-9]*"`. – deltragon Apr 01 '22 at 08:46
  • that might be, but it still didn't work correctly when using validators. It wouldn't allow values greater than 9. I replaced the pattern with `pattern="\d*"` and it now works fine – Ted Apr 11 '22 at 09:36
3

Set step attribute to any float number, e.g. 0.01 and you are good to go.

dippas
  • 58,591
  • 15
  • 114
  • 126
Mantas K.
  • 84
  • 5
3

I was working oh Chrome and had some problems, even though I use html attributes. I ended up with this js code

$("#element").on("input", function(){
        var value = $(this).val();

        $(this).val("");
        $(this).val(parseInt(value));

        return true;
});
a.valchev
  • 388
  • 4
  • 10
  • I ended up using this as well with 1 minor tweak; I changed parseInt(value) to parseInt(value.replace('.', ''). This allowed me to paste 1.56 and keep the displayed value at 156 instead of 1. – codescribblr Jun 01 '18 at 13:50
3

Maybe it does not fit every use case, but

<input type="range" min="0" max="10" />

can do a fine job: fiddle.

Check the documentation.

Luca Fagioli
  • 12,722
  • 5
  • 59
  • 57
  • @ViacheslavDobromyslov Not sure what you are looking for, but I remind you the OP question: "Is there another input _type_ or perhaps an _attribute_ that would **restrict** the input to just unsigned **integers**?" Why do you sentence this answer as "not working", if it does **exactly** what the OP asked? – Luca Fagioli Feb 05 '21 at 09:30
  • Because it's near to impossible to input a value from ~9 quadrillion integers using the proposed range input control. – Viacheslav Dobromyslov Feb 05 '21 at 14:24
  • 1
    @ViacheslavDobromyslov Where this 9 quadrillions requirement come from? The OP didn't ask about that. This answer replies the OP question, no what you have in mind. – Luca Fagioli Feb 06 '21 at 17:39
  • He has not asked for a solution with 10 numbers in a row. Your solution does not work for any range. – Viacheslav Dobromyslov Feb 06 '21 at 17:46
  • @ViacheslavDobromyslov It does a good job especially with short ranges. Give it a try, I'm sure it would fit well your necessities. – Luca Fagioli Feb 07 '21 at 07:17
3

have you tried setting the step attribute to 1 like this

<input type="number" step="1" /> 
dippas
  • 58,591
  • 15
  • 114
  • 126
DevTeamExpress
  • 183
  • 2
  • 9
2

Yes, HTML5 does. Try this code (w3school):

<!DOCTYPE html>
<html>
<body>

<form action="">
  Quantity (between 1 and 5): <input type="number" name="quantity" min="1" max="5" />
  <input type="submit" />
</form>

</body>
</html>

See the min and max paremeter? I tried it using Chrome 19 (worked) and Firefox 12 (did not work).

Valentin Despa
  • 40,712
  • 18
  • 80
  • 106
wilsonfoz
  • 867
  • 8
  • 9
2

Set step="any" . Works fine. Reference :http://blog.isotoma.com/2012/03/html5-input-typenumber-and-decimalsfloats-in-chrome/

dippas
  • 58,591
  • 15
  • 114
  • 126
udit mittal
  • 529
  • 3
  • 14
2

Currently, it is not possible to prevent a user from writing decimal values in your input with HTML only. You have to use javascript.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Michal
  • 4,952
  • 8
  • 30
  • 63
1
var valKeyDown;
var valKeyUp;


function integerOnly(e) {
    e = e || window.event;
    var code = e.which || e.keyCode;
    if (!e.ctrlKey) {
        var arrIntCodes1 = new Array(96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 8, 9, 116);   // 96 TO 105 - 0 TO 9 (Numpad)
        if (!e.shiftKey) {                          //48 to 57 - 0 to 9 
            arrIntCodes1.push(48);                  //These keys will be allowed only if shift key is NOT pressed
            arrIntCodes1.push(49);                  //Because, with shift key (48 to 57) events will print chars like @,#,$,%,^, etc.
            arrIntCodes1.push(50);
            arrIntCodes1.push(51);
            arrIntCodes1.push(52);
            arrIntCodes1.push(53);
            arrIntCodes1.push(54);
            arrIntCodes1.push(55);
            arrIntCodes1.push(56);
            arrIntCodes1.push(57);
        }
        var arrIntCodes2 = new Array(35, 36, 37, 38, 39, 40, 46);
        if ($.inArray(e.keyCode, arrIntCodes2) != -1) {
            arrIntCodes1.push(e.keyCode);
        }
        if ($.inArray(code, arrIntCodes1) == -1) {
            return false;
        }
    }
    return true;
}

$('.integerOnly').keydown(function (event) {
    valKeyDown = this.value;
    return integerOnly(event);
});

$('.integerOnly').keyup(function (event) {          //This is to protect if user copy-pastes some character value ,..
    valKeyUp = this.value;                          //In that case, pasted text is replaced with old value,
    if (!new RegExp('^[0-9]*$').test(valKeyUp)) {   //which is stored in 'valKeyDown' at keydown event.
        $(this).val(valKeyDown);                    //It is not possible to check this inside 'integerOnly' function as,
    }                                               //one cannot get the text printed by keydown event 
});                                                 //(that's why, this is checked on keyup)

$('.integerOnly').bind('input propertychange', function(e) {    //if user copy-pastes some character value using mouse
    valKeyUp = this.value;
    if (!new RegExp('^[0-9]*$').test(valKeyUp)) {
        $(this).val(valKeyDown);
    }
});
Sarthak
  • 57
  • 5
1

Posting it, if anyone requires it in future

const negativeValuePrevent = (e) => {
    const charCode = e.which ? e.which : e.keyCode;
    if(charCode > 31 && (charCode < 48 || charCode > 57) 
    && charCode !== 46){
      if(charCode < 96 || charCode > 105){
        e.preventDefault();
        return false;
      }
    }
    return true;
  };
Nitish Jha
  • 27
  • 4
1

From the specs

step="any" or positive floating-point number
Specifies the value granularity of the element’s value.

So you could simply set it to 1:

dippas
  • 58,591
  • 15
  • 114
  • 126
David Hedlund
  • 128,221
  • 31
  • 203
  • 222
-1

Short and user friendly

This solution supports tab, backspace, enter, minus in intuitive way

<input type=text onkeypress="return /^-?[0-9]*$/.test(this.value+event.key)">

however it not allow to change already typed number to minus and not handle copy-paste case.

As alternative you can use solution based on R. Yaghoobi answer which allow to put minus and handle copy-paste case, but it delete whole number when user type forbidden character

<input type=text oninput="this.value= ['','-'].includes(this.value) ? this.value : this.value|0">

NOTE: above inline solutions use only in small projects. In other case opaque them in functions and move to your js files.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
  • Inline event handlers like `onclick` are [bad practice](/q/11737873/4642212). They’re an [obsolete, cumbersome, and unintuitive](/a/43459991/4642212) way to listen for events. Always [use `addEventListener`](//developer.mozilla.org/en/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_%E2%80%94_dont_use_these) instead. Please _never_ suggest or encourage these attributes. The last browser that still needs them reached end of life nearly two decades ago. The [`keypress` event](//developer.mozilla.org/en/docs/Web/API/Element/keypress_event) is deprecated. – Sebastian Simon Dec 03 '22 at 19:53
  • 1
    @SebastianSimon [update](https://stackoverflow.com/a/54769527/860099) yourself – Kamil Kiełczewski Dec 03 '22 at 20:05
  • This isn’t React, Angular, or Vue.js. These are DOM 0 event listeners. They don’t cooperate with modern JavaScript. – Sebastian Simon Dec 03 '22 at 20:08
-1

The integer input would mean that it can only take positive numbers, 0 and negative numbers too. This is how I have been able to achieve this using Javascript keypress.

<input type="number" (keypress)="keypress($event, $event.target.value)" >

keypress(evt, value){
  
    if (evt.charCode >= 48 && evt.charCode <= 57 || (value=="" && evt.charCode == 45))       
    {  
      return true;
    }
    return false;
}

The given code won't allow user to enter alphabets nor decimal on runtime, just positive and negative integer values.

Farhan
  • 61
  • 8
-4

In the Future™ (see Can I Use), on user agents that present a keyboard to you, you can restrict a text input to just numeric with input[inputmode].

weston
  • 1,972
  • 17
  • 17
  • `inputmode` is mostly for hand-held devices and will trigger the correct keyboard layout, but for "normal" computers with keyboards, it iwll not prevent entering whatever you want. – vsync Oct 18 '13 at 10:47