CoderPi
CoderPi

Reputation: 13211

HTML5 input range: allow "min" bigger then "max" (from to)

on the <input type="range" /> I need the min=""-value to be bigger than the max=""-value,
for example values from 100 to 0:

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

Is this possible in some way? It would be fine to use JavaScript.

Here a Demo of what I mean:

0 to 100: (this is working)
<input type="range" min="0" max="100" step="any" style="width: 100%" 
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />

100 to 0: (not working in IE, Edge, Firefox and Chrome*)
<input type="range" min="100" max="0" step="any" style="width: 100%"
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />

100 to 0: hack
<input type="range" min="0" max="100" step="any" style="width: 100%; direction: rtl;"
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />

<div id="test"></div>

I basicly want a from - to slider, not min - max


EDIT: I don't want this to happen: (slider colors are flipped as well) enter image description here Wich is done by my example direction: rtl; but also transform: scaleX(-1); and transform: rotate(180deg);

Upvotes: 5

Views: 3832

Answers (4)

Djave
Djave

Reputation: 9329

To answer your question, it is not possible to have the minimum value higher than the maximum value or include a from or to attribute without majorly hacking the input

Just make sure that the final number you are using is 100 minus your slider size.

I would also add a hidden input, and update that input's value – as you're going to mess with the actual value of the slider with this method.

0 to 100: (this is working)
<input type="range" min="0" max="100" step="any" style="width: 100%" 
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />

100 to 0: (not working in IE, Edge, Firefox and Chrome*)
<input type="range" min="0" max="100" step="any" style="width: 100%"
       oninput="document.getElementById('test').innerHTML = 100 - parseInt(this.value)" 
       onchange="document.getElementById('test').innerHTML = 100 - parseInt(this.value); document.getElementById('slider-value').value = 100 - parseInt(this.value)" />
<br />
Hidden input <input type="text" id="slider-value">
<div id="test"></div>

Edit 2: There is this overview by w3 https://www.w3.org/wiki/HTML/Elements/input/range and unfortunately the range input doesn't have the attributes you require. If you need to make a bespoke input, you can sort of cheat. Funnily enough, I made a range based input that would accept mouse wheel events – to an extent – but it may be useful to see how I hid the input and replaced it with another interface: http://codepen.io/EightArmsHQ/pen/CfmeE

Upvotes: 5

CoderPi
CoderPi

Reputation: 13211

I found another way to do this without the side-effects I was concerned about:

it unifyes the appearance of the slider in all browsers, wich otherwise is very different. (the elements value however will always be from 0 to 1)

function sliderOutput(percentage, from, to) {
  document.getElementById('test').innerHTML = fromTo(percentage, from, to)
}

function fromTo(percentage, from, to) {
  return from + (to - from) * percentage
}
input[type="range"] {
    width: 150px; /* default diffrent in every Browser */
    height: 20px; /* default diffrent in every Browser */
    background-color: lightgray; /* default transparent or white in FireFox */
    margin: 0; /* Edge and Chrome */
    padding: 0; /* IE and FireFox */
    outline: none; /* Chrome */
    -webkit-appearance: none; /* Chrome fix */
}

    input[type="range"]::-moz-range-track {
        border: inherit;
        background: transparent;
    }

    input[type="range"]::-ms-track {
        border: inherit;
        color: transparent;
        background: transparent;
    }

    input[type="range"]::-ms-fill-lower,
    input[type="range"]::-ms-fill-upper {
        display: none;
    }

    input[type="range"]::-ms-tooltip {
        display: none;
    }

    /* Thumb-Classes can not be merged */

    input[type="range"]::-webkit-slider-thumb {
        width: 30px;
        height: 20px;
        border: none;
        background-color: gray;
        -webkit-appearance: none; /* Chrome fix */
    }

    input[type="range"]::-moz-range-thumb {
        width: 30px;
        height: 20px;
        border: none;
        border-radius: 0;
        background-color: gray;
    }

    input[type="range"]::-ms-thumb {
        width: 30px;
        height: 20px;
        border: 0; /* IE */
        background-color: gray;
    }
0 to 100:
<input type="range" min="0" max="1" step="any" step="any"
        oninput="sliderOutput(this.value, 0, 100)"
        onchange="sliderOutput(this.value, 0, 100)" />
<br />
100 to 0:
<input type="range" min="0" max="1" step="any" step="any"
        oninput="sliderOutput(this.value, 100, 0)"
        onchange="sliderOutput(this.value, 100, 0)" />
<br />
<br />
Value: <span id="test"></span>

Upvotes: 1

Robert McKee
Robert McKee

Reputation: 21487

Four different approaches, each with slight quirks.

  • You can change the direction via direction: rtl, but it changes what part of the slider is highlighted in IE use #fixed1::-ms-fill-lower { background-color: transparent; } to remove the highlight.
  • You can horizontally flip the slider via transform: scaleX(-1), but that puts the shading of the pointer in firefox on the wrong side.
  • You can rotate the slider via transform: rotate(180deg), but that put the pointer upside down in firefox.
  • You can use a 100-x hack, but the tooltip on the slider shows the incorrect value.

I would probably use direction: rtl, and if the highlighting bothers you see about removing the styling in IE if it's possible.

#fixed1 { direction: rtl}
#fixed2 { transform: scaleX(-1); }
#fixed3 { transform: rotate(180deg); }

/* IE fixes */
#fixed1::-ms-fill-upper {
    background-color: rgba(54, 153, 201, 1);
}
#fixed1::-ms-fill-lower {
    background-color: transparent;
}
#fixed2::-moz-range-thumb {
  transform: scaleX(-1);
}
#fixed3::-moz-range-thumb {
  transform: rotate(180deg);
}
0 to 100: (this is working)
<input type="range" min="0" max="100" step="any" style="width: 100%" 
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />

100 to 0: rtl (highlighted part different in IE)
<input id='fixed1' type="range" min="0" max="100" step="any" style="width: 100%"
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />
100 to 0: flip (shading on wrong side in firefox)
<input id='fixed2' type="range" min="0" max="100" step="any" style="width: 100%"
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />
100 to 0: rotate (pointer upside down in firefox)
<input id='fixed3' type="range" min="0" max="100" step="any" style="width: 100%"
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />
100 to 0: hack (tooltip is wrong)
<input type="range" min="0" max="100" step="any" style="width: 100%;"
       oninput="document.getElementById('test').innerHTML = 100 - this.value" 
       onchange="document.getElementById('test').innerHTML = 100 - this.value" />
<br />

<div id="test"></div>

Upvotes: 1

Spencer Wieczorek
Spencer Wieczorek

Reputation: 21565

Keep the same values for min and max but rotate it around by 180 degrees. Or you can apply scaleX(-1) to flip it horizontally.

#flip {
    -ms-transform: rotate(180deg);
    -webkit-transform: rotate(180deg); 
    transform: rotate(180deg);
} 

#flip {
    -ms-transform: scaleX(-1); 
    -webkit-transform: scaleX(-1); 
    transform: scaleX(-1);
} 
0 to 100: (this is working)
<input type="range" min="0" max="100" step="any" style="width: 100%" 
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />

100 to 0: (not working in IE, Edge, Firefox and Chrome*)
<input id="flip" type="range" min="0" max="100" step="any" style="width: 100%"1
       oninput="document.getElementById('test').innerHTML = this.value" 
       onchange="document.getElementById('test').innerHTML = this.value" />
<br />

<div id="test"></div>

Upvotes: 1

Related Questions