Reputation: 8768
When I create an HTML <input type="number"/>
with step="0.010000000000000009"
. I can only click the button to increase the value once to fill in the min
value and then only once for the first increase by the step value, then it gets stuck at this value and further clicks have no effect. I can only reproduce this with min="1.2" max="1.3"
.
All other combinations of min
, max
and step
I tried allow to click the button multiple times until it reaches max in the defined steps.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>input with decimal step</title>
</head>
<body>
<input type="number" min="1.2" max="1.3" step="0.010000000000000009"/>
</body>
</html>
Upvotes: 2
Views: 760
Reputation: 155438
I believe that, according to the HTML5 Living Specification, your <input />
element "suffers from step-mismatch":
Following the spec w.r.t. your case...
The step
value is 0.010000000000000009
(from parseFloat
).
The step-scale-factor
value is always 1
for <input type="number" />
The step-base
is the min
attribute, which is 1.2
.
The allowed-value-step
is step
* step-scale-factor
which is 1 * 0.010000000000000009 === 0.010000000000000009
.
Re: "Constraint validation", the spec says this:
Constraint validation: When the element has an
allowed-value-step
, and the result of applying the-algorithm-to-convert-a-string-to-a-number to the string given by the element'svalue=""
is a number, and that number subtracted from thestep-base
is not an integral multiple of theallowed-value-step
, the element is suffering from a step mismatch.
I'll rephrase that to this...:
allowed-value-step
and numeric value=""
attribute.
<input/>
is non-empty, such as clicking the up/down buttons once to give it a value of 1.2
)1.2
(the step-base
) from 1.2
(the value=""
) to give 0
.0
is not an integral multiple of 0.010000000000000009
.Now, w.r.t. your findings:
I can only click the button to increase the value once to fill in the
min
value
Yes, that follows the HTML5 spec: the initial value=""
is empty, so browsers will choose the next valid highest value which is the min="1.2"
value.
and then only once for the first increase by the step value
Yes, that's because the next step is 1.2 + 0.010000000000000009
which is 1.210000000000000009
- which both browsers truncate the display to 1.21
, however as soon as this happens we see a difference in browser behaviour:
HTMLInputElement.validity.stepMismatch
to true
and disables the up/down buttons due to the step-mismatch condition.HTMLInputElement.validity.stepMismatch === false
.Here's a snippet that shows validity information:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>input with decimal step</title>
</head>
<body>
<input id="inp" type="number" min="1.2" max="1.3" step="0.010000000000000009" />
<ul id="eventsList"></ul>
<script>
const inp = document.getElementById('inp');
const ul = document.getElementById('eventsList');
inp.addEventListener( 'input', logInfo );
inp.addEventListener( 'change', logInfo );
inp.addEventListener( 'click', logInfo );
function logInfo( e ) {
const li = document.createElement('li');
li.textContent = e.type + ". Value: " + inp.value + ", valid: " + inp.validity.valid + ", stepMismatch: " + inp.validity.stepMismatch;
ul.appendChild( li );
}
</script>
</body>
</html>
1.2
, 1.21
, 1.22
, 1.23
, ..., 1.28
, to 1.29
) before it stops, though it never reports stepIsmatch: true
.1.2
and 1.21
) before it sets stepMismatch: true
.My money's on Chrome doing their own thing given their interpretation (or at least, their implementation) of the spec is more forgiving and is less likely to result in end-user-frustration when step
is set to a strange value.
What's interesting is that the Number
type in browsers seems able to accurately represent 0.010000000000000009
without any tell-tale IEEE 754 rounding (ditto Python), whereas C#/.NET's Single
(32-bit) and Double
(64-bit) floating-point types both choke and give me rather bad approximations.
Upvotes: 4