简体   繁体   中英

HTML `<input type="number">` element - Customize increment value of arrow buttons independently from `step`

I have an HTML <input> element with type="number" :

数字输入

I want to use a step value of 1. That is, any integer is allowed. However, I would also like the arrow buttons to increment/decrement the value of the input by some value, for example, 5. Is this possible?

From the MDN docs , I can't find a way to accomplish this using HTML alone. I would also accept an answer involving intercepting the input event using javascript to change the value of the input, but I don't know of a way to distinguish between a change due to keypresses vs. a change due to clicking the arrow buttons.

You can always capture the input in javascript and convert the values to an integer with parseInt and use the normal step to control the arrow stepping.

With this method you don't have to worry about distinguishing between the stepping and input as the steps will already be integers anyway.

 let nums = document.querySelectorAll("input[type='number']"); nums.forEach(function(e){ e.addEventListener("input",function(el){ el.target.value = parseInt(el.target.value) }); });
 <input type="number" step="4" />

Currently it is not possible to capture a click on the spinners directly, but there are some ways to detect a click on them .

By using different events it is possible to adjust the step size for the moment. But it may cause some unwanted effect if the user uses the mouse to click on a spinner, keeps the mousekey pressed and presses an arrow key up/down:

 // fires ones right before the value is changed for the first time input.addEventListener("mousedown", ({ target }) => target.setAttribute("step", 5)); input.addEventListener("mouseup", ({ target }) => target.setAttribute("step", 1)); // fires after release of the mouse key, even if the user moved the mouse input.addEventListener("change", ({ target }) => target.setAttribute("step", 1));
 <input id="input" type="number" step="1" value="0" />

<label> Overlay

Make a <label> that lays over the spinner button of the <input> and in the eventhandler use the .stepUp() and .stepDown() methods when the <label> is clicked.

In Example A , the <label> is outlined in red and the two nested <b> are outlined in blue. The outlines are just for the demo of course and can be easily removed. See Example A

XY Coordinates

Another way is to place an abspos ( abs olute pos itioned) <input> in a relpos container and change the step attribute if the click is within the xy coords of the <input> spinner button. See Example B .

Details are commented in both Example A and B

Example A

<label> overlay

 // Bind <label> to the click event document.querySelector('.spinner').onclick = incDec; function incDec(e) { // Reference the tag the user clicked const clk = e.target; // Reference the <input> const int = this.previousElementSibling; // If the user clicked .inc... if (clk.matches('.inc')) { //...Increment <input> value by 5 int.stepUp(5); } // If the user clicked .dec... if (clk.matches('.dec')) { //...Decrement <input> value by 5 int.stepDown(5); } }
 .spinner { position: relative; top: -4px; right: 24px; z-index: 1; display: inline-flex; flex-flow: column nowrap; justify-content: center; align-items: center; width: 16px; height: 18px; outline: 1px dashed red; } .spinner b { display: inline-block; width: 100%; height: 50%; outline: 1px blue solid }
 <input id='int' type='number' min='0' step='1'> <label for='int' class='spinner'><b class='inc'></b><b class='dec'></b></label>

Example B

XY Coordinates

 // Reference <form> const UI = document.forms.UI; // Reference all form controls const IO = UI.elements; // Reference <fieldset> const set = IO.set; // Reference <input> const int = IO.int; // Define an empty array to xy coords let point = []; // Bind <fieldset> to 'mousemove' event set.onmousemove = xy; // Bind <input> to 'mousedown' event int.onmousedown = setPoint; /* Bind <input> to 'mouseup' event restore step attribute back to 1 */ int.onmouseup = e => e.target.step = 1; /* Assigns current xy coords within the perimeter of <fieldset> to array point */ function xy(e) { let x = e.clientX; let y = e.clientY; point[0] = x; point[1] = y; } /* Checks if the user is clicking the <input> spinner. If user is, then step attribute is changed to 5 */ function setPoint(e) { let x = point[0]; let y = point[1]; if (x > 215 && x < 231 && y > 30 && y < 51) { this.step = 5; } }
 html { font: 300 62.5%/1 Consolas; } fieldset { position: relative; width: 24rem; height: 5rem; } input { position: absolute; left: 2.5rem; top: 1.85rem; width: 19rem; font: inherit; font-size: 1.6rem; text-align: center; }
 <form id='UI'> <fieldset id='set'> <input id='int' type='number' min='0' step='1'> </fieldset> </form>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM