A common UI pattern for a range slider is to allow the user to move the slider and display the value of it somewhere on the page, changing the displayed value as the user moves the slider.
I think the expected behaviour in such a case is that the value should display instantly, as the user is moving the slider, rather than the page waiting for the slider to finish moving before the displayed value is updated. I suppose there could be cases where you prefer a delay over instant results, but I think the expected behaviour is to display the results instantly.
As you’ll see in the videos below and in your own testing, the behaviour of the input
event compared to the change
event is not exactly the same in different browsers when applied to a range slider.
Let’s look at how these events behave in the different browsers. The code I’ll be using is embedded in the CodePen example below:
See the Pen
Using the change event with a Range Slider by Louis Lazaris (@impressivewebs)
on CodePen.
Swap change
with input
to see the differences I’ll be discussing. The results described are observed on OSX and Windows 7.
Note: Opera is equivalent to Chrome in these tests because it now has the same rendering engine.
oninput in Chrome
Observations:
- Works as expected, the
input
event fires immediately when the slider is adjusted, which is demonstrated by the value changing on the page instantly. - Focusing and adjusting the slider with the keyboard has the same result.
onchange in Chrome
Observations:
- The
change
event does not fire immediately, demonstrated by the fact that the value on the page does not change until the slider stops moving. - Keyboard interaction, however, is the same as
oninput
, with the value on the page updating immediately.
oninput in Firefox
Observations:
- Same results as
oninput
in Chrome; changes happen immediately. - Keyboard results the same, changes appear immediately.
onchange in Firefox
Observations:
- Same results as Chrome; the value doesn’t change on the page until the slider stops moving.
- When moving the slider with the keyboard, the value does not update until the slider is blurred, or unfocused. This is the only difference from the behaviour in Chrome.
Update (May 11, 2020): This problem is now corrected in Firefox, as outlined in this bug report.
oninput in IE11
Observations:
oninput
is not recognized at all when used on a range slider. The same event, however, does fire when used on a text input.- Although
oninput
doesn’t fire, the value of the slider is displayed in a native tooltip, which doesn’t happen on the other browsers. - The keyboard likewise has no effect on the value and the native tooltip is not displayed.
onchange in IE11
Observations:
- Works the same way as
oninput
in Chrome and Firefox; the value changes immediately while the slider is still moving. - Keyboard results are the same, the value updates immediately.
What’s the Correct Behaviour?
The WHATWG spec describes the expected behaviour as follows:
The
input
event fires whenever the user has modified the data of the control. Thechange
event fires when the value is committed, if that makes sense for the control, or else when the control loses focus. In all cases, theinput
event comes before the correspondingchange
event (if any).
The same description is found in the W3C version of the spec.
For oninput
, Chrome and Firefox have the correct behaviour with both mouse and keyboard interaction. But Firefox seems to have the most accurate behaviour for onchange
.
As shown in the quote above, onchange
should always fire after oninput
, so the fact that Firefox waits for the range slider to lose focus before firing the event (for both mouse and keyboard) seems to be the correct behaviour. Chrome does not wait until the control is unfocused when using the keyboard, but it does so with the mouse.
IE11, of course, is completely wrong on two counts: It doesn’t recognize oninput
when applied to a range slider and it responds to onchange
as if it was oninput
, firing the event immediately instead of waiting until the slider stops moving or loses focus.
As a side point here, the HTML4 spec seemed to define the behaviour a little more clearly:
The
onchange
event occurs when a control loses the input focus and its value has been modified since gaining focus.
Though when that was written, there was no such thing as type="range"
for form inputs.
Sources and Bug Reports
There has been discussion on this behaviour in the bug trackers for the various browsers, and I believe the wording in the spec was updated to be less ambiguous — although I still feel that it’s not 100% clear if Firefox’s keyboard behaviour is the correct one.
Here are some relevant links in addition to the ones provided in the article above:
- Firefox bug report – Closed as “invalid” since Firefox’s behaviour is correct.
- IE11 bug report on missing
input
event, still unresolved. - Chrome bug report which I filed myself to see if the different keyboard behaviour can be corrected to agree with Firefox.
- W3C bug report, which attempts to make the spec less ambiguous.
- change event on MDN, which explains that “different browsers do not always agree whether a
change
event should be fired for certain types of interaction.”
Great research and even greater with movies to show. =)
If I am not misstaken onchange first appeared on the select element and at first it was instant as oninput is today but designers misused it as navigation menus where users selected an option with some name and a URL as value and
location.href
was set to that value. So when a keyboard user arrived they couldn’t use the site cause they were being navigated away from the page before they could get passed first option. When this was changed and later standardised there was a great disturbance in the Community, as if millions of designers suddenly cried out in terror and were suddenly forced to accompany all navigation select boxes with a button. Usability has sadly never been prioritised among most designers.Interesting, thanks for that. That would certainly explain why
onchange
waits for unfocus before applying.I made a few observations about these two events in june on Twitter:
https://twitter.com/MaximeEuziere/status/478149970881966080
It’s good to see them described in a real article. Good job!
M.
Nice.
Yes, I had actually noticed this a number of months ago myself (back in April, actually!) but just never got around to posting anything about it.
Used this idea with a spin–button control. Works great, updates every value change.
thank you. I have been trying to solve the update problem for hours.
Thanks for sharing this.
I was struggling to get Material Design Lite slider values on onChange event. Your details explanation saved me a lot of time.
Thank you very much, you saved me.
This is still valid as of November 2018. Thanks for the super clear demonstration. Probably saved me a few hours bug hunting.
i’ve recently implemented a slider which taught me these lessons. I am still researching solutions, thus, i just found your page in a Google search result list.
Unlike you, i want ie11 support, so oninput is no good. I decided to include both events inline and it works very well. Newer browsers use oninput and ie11 falls back to onchange:
f o r m onchange= oninput =
anyone know how to get this into a boolean? as ? x : y
i’d like to drop my inline solution but i’m not a js guru.