Coder Perfect

While dragging in Firefox, the onchange event on input type=range does not fire.


When I experimented with input type=”range”>, Firefox only fires a onchange event if the slider is dragged to a new location, whereas Chrome and others fire onchange events while the slider is being dragged.

How can I get it to happen when I drag in Firefox?

Asked by Prasanth K C

Solution #1

Onchange should only be triggered when the user releases the mouse, according to Chrome and Safari. To get continuous updates, use the oninput event, which will collect live updates from the mouse and keyboard in Firefox, Safari, and Chrome.

However, because oninput isn’t supported in IE10, you’ll have to combine the two event handlers, as shown here:

<span id="valBox"></span>
<input type="range" min="5" max="10" step="1" 
   oninput="showVal(this.value)" onchange="showVal(this.value)">

For further information, see this Bugzilla topic.

Answered by Frederik

Solution #2


I give a no-jQuery cross-browser desktop and mobile ability to respond consistently to range/slider interactions, which is currently unavailable in current browsers. It effectively requires all browsers to replicate Internet Explorer 11’s on(“change”… event for either their on(“change”… or on(“input”… events. The new feature is called…

function onRangeChange(r,f) {
  var n,c,m;

ll be called after any interaction that changes the range/slider value, but not after interactions that do not modify that value, such as initial mouse or touch interactions at the current slider position or when the slider is moved off either end.


As of early June 2016, different browsers respond to range/slider usage in different ways. There are five possibilities that are relevant:

The following table shows how at least three different desktop browsers differ in their behaviour with respect to which of the above scenarios they respond to:


The onRangeChange function ensures that range/slider interactions are handled consistently and predictably across browsers. It compels all browsers to observe the rules given in the table below:

In IE11, the code essentially maintains the status quo, i.e., it permits the “change” event to work normally, while the “input” event is rendered obsolete because it never fires. The “change” event is effectively suppressed in other browsers (to prevent extra and sometimes not-readily-apparent events from firing). Furthermore, the “input” event only fires its listener when the value of the range/slider changes. Because the listener is effectively silenced in cases 1, 4, and 5 from the preceding list, this happens in some browsers (e.g. Firefox).

(If you really need a listener in any scenario 1, 4, or 5, you could use the “mousedown”/”touchstart,” “mousemove”/”touchmove,” and/or “mouseup”/”touchend” events.) The scope of this response does not allow for such a solution.)

Mobile Browser Functionality:

This code has been tested on desktop browsers but not on mobile browsers. However, MBourne has demonstrated that my method here “appears to work in every browser I could discover (Win desktop: IE, Chrome, Opera, FF; Android Chrome, Opera, and FF, iOS Safari)” in another answer on this page. (Many thanks to MBourne.)


To use this solution, include the onRangeChange function from the summary above (simplified/minified) or the demo code snippet below (functionally identical but more self-explanatory) in your own code. Invoke it by saying:

onRangeChange(myRangeInputElmt, myListener);

where myRangeInputElmt is the input type=”range”> you want. myListener is the listener/handler function you wish to be called when “change”-like events occur.

If desired, your listener can be parameter-less, or it can use the event parameter, in which case either of the following would work:

var myListener = function() {...


var myListener = function(evt) {...

(Removing the event listener from the input element (using removeEventListener, for example) is not covered in this answer.)

Demo Description:

The universal solution is provided by the method onRangeChange in the code excerpt below. The remainder of the code is just an example of how to utilize it. Any variable that starts with my… has no bearing on the universal answer and is solely used for demonstration purposes.

The range/slider value, as well as the number of times the regular “change,” “input,” and custom “onRangeChange” events have fired, are all displayed in the demo (rows A, B and C respectively). Note the following as you interact with the range/slider when running this sample in different browsers:

Demo Code:


While I did most of the work myself, I was inspired by MBourne’s response. That other solution claimed that the “input” and “change” events could be combined, with the resulting code working in both desktop and mobile browsers. However, the code in that answer causes hidden “additional” events to be triggered, which is problematic in and of itself, and the events fired change between browsers, which is another issue. These issues are addressed by my implementation.


The range slider events in JavaScript affect the input browser compatibility. no-jQuery cross-browser desktop mobile

Answered by Andrew Willems

Solution #3

Because it deserves to be its own answer rather than a remark under a less relevant answer, I’m presenting it as an answer. I prefer this way to the acceptable answer since it allows me to keep all of the js in a separate file from the HTML.

Jamrelian supplied the answer in his remark below the acceptable answer.

$("#myelement").on("input change", function() {
    //do something

However, you should be aware of Jaime’s comment.

In other words, it will fire the event when you stop moving the mouse and then again when you let off of the mouse button.

This is a non-issue in terms of the change event and input event causing the functionality to trigger twice.

It’s quite unlikely that there will be a problem when the change event fires if you have a function that triggers on input.

When you drag a range input slider, input fires quickly. In comparison to the ocean of water that is the input events, fretting about one more function call triggering at the end is like worrying about a single drop of water.

The reason for inserting the change event in the first place is to ensure browser compatibility (mainly with IE).

Answered by Daniel Tonon

Solution #4

UPDATE: I’m keeping this response up as an example of how to use mouse events in desktop (but not mobile) browsers to employ range/slider interactions. However, I’ve now written an entirely alternative and, in my opinion, superior response elsewhere on this page, which takes a different approach to offering a cross-browser desktop and mobile solution to this problem.

Original answer:

Summary: A cross-browser, plain JavaScript (i.e. no-jQuery) solution to allow reading range input values without using on(‘input’… and/or on(‘change’… which work inconsistently between browsers.

Because there is still browser discrepancy as of today (late February 2016), I’m releasing a fresh workaround here.

The issue: When utilizing a range input, such as a slider, on(‘input’… in Mac and Windows Firefox, Chrome, and Opera, as well as Mac Safari, offers continually updated range values, whereas on(‘change’… only reports the range value upon mouse-up. On the other hand, on(‘input’… does not operate in Internet Explorer 11 and on(‘change’… is constantly updated.

Using the mousedown, mousemove, and (potentially) mouseup events, I present two ways for getting identical continuous range value reporting in all browsers using vanilla JavaScript (i.e. no jQuery).

Strategy 1: Make it shorter but inefficient.

You can use this first approach, which uses mousesdown and mousemove but not mouseup, if you prefer shorter code to more efficient code. This reads the slider as needed, but fires unnecessarily for any mouse-over events, even if the user hasn’t clicked or dragged the slider. It basically reads the range value after’mousedown’ and during’mousemove,’ slightly delaying each event with requestAnimationFrame.

Strategy 2: Takes a little longer, but it’s more effective.

You can use the following approach, which employs mousedown, mousemove, and mouseup, if you require more efficient code and can handle larger code length. This likewise reads the slider as needed, but when the mouse button is released, it stops reading it. The main difference is that it only listens for’mousemove’ after’mousedown,’ and it only stops listening for’mousemove’ after’mouseup.’

Demo: A more detailed explanation of why the above workarounds are needed and how to put them in place.

The following code explains various features of this strategy in further detail. The demonstration includes explanations:

Answered by Andrew Willems

Solution #5

Andrew Willem’s solutions are not compatible with mobile devices.

Here’s a tweak to his second method that works on Edge, IE, Opera, Firefox, Chrome, iOS Safari, and mobile equivalents (that I tested):

Update 1: I removed the “requestAnimationFrame” section because I believe it is unnecessary:

var listener = function() {
  // do whatever

slider1.addEventListener("input", function() {
  slider1.addEventListener("change", listener);
slider1.addEventListener("change", function() {
  slider1.removeEventListener("input", listener);

Update 2: In response to Andrew’s amended answer from June 2nd, 2016, I’ve written the following:

Thank you very much, Andrew – That appears to work in all of the browsers I’ve tried (Win desktop: IE, Chrome, Opera, FF; Android Chrome, Opera and FF, iOS Safari).

Update 3: solution for “oninput in slider”

The following appears to work in all of the browsers listed above. (At this time, I’m unable to locate the original source.) I was using this, but it failed on IE, so I started seeking for another, which is how I landed here here.

if ("oninput" in slider1) {
    slider1.addEventListener("input", function () {
        // do whatever;
    }, false);

However, when I looked at your solution, I observed that this was functioning with IE again – possibly there was another conflict.

Answered by MBourne

Post is based on