204

I am making a website where I want to use range slider(I know it only supports webkit browsers).

I have integrated it fully and works fine. But I would like to use a textbox to show the current slide value.

I mean if initially the slider is at value 5, so in text box it should show as 5, when I slide the value in text box should change.

Can I do this using only CSS or html. I want to avoid JQuery. Is it possible?

3
  • 2
    You can't do this without javascript. Commented Apr 4, 2012 at 5:12
  • 4
    You can almost do this with css using :before/:after, content and attr(), like this. However, the :before/:after pseudo-elements actually eat up some of the slider's range (although maybe that's fixable), and most importantly, the values aren't updated if the slider is manipulated. Nevertheless, I thought it would be interesting to leave this here. It might become possible in the future. Commented Jul 2, 2013 at 15:47
  • 3
    Fixing @waldir 's solution results in jsfiddle.net/RjWJ8 though it still uses javascript to update the value attribute from the property. Commented Mar 20, 2014 at 15:21

15 Answers 15

358

For those who are still searching for a solution without a separate javascript code. There is little easy solution without writing a javascript or jquery function:

<input type="range" value="24" min="1" max="100" oninput="this.nextElementSibling.value = this.value">
<output>24</output>

JsFiddle Demo

If you want to show the value in text box, simply change output to input.


Point to note: It is still Javascript written within your html, we can write something like below in js to do similar thing:

 document.registrationForm.ageInputId.oninput = function(){
    document.registrationForm.ageOutputId.value = document.registrationForm.ageInputId.value;
 }

Instead of element's id, name could also be used, both are supported in modern browsers.

Sign up to request clarification or add additional context in comments.

12 Comments

+1 know I know about <output>. Only problem is that E.I doesn't support it though. (W3School) w3schools.com/tags/tryit.asp?filename=tryhtml5_output
It's still javascript, and it's worse to bind oninput on form element than on input element itself.
@cuixiping, we can bind oninput on element instead of form, i just did it to show example.
Forgive this late and noob question, but how does the handler refer to rangeInput and amount by their HTML names?
I've edited the question's code to the bare minimum, stripping unnecessary code
|
147

This uses javascript, not jquery directly. It might help get you started.

function updateTextInput(val) {
          document.getElementById('textInput').value=val; 
        }
<input type="range" name="rangeInput" min="0" max="100" onchange="updateTextInput(this.value);">
<input type="text" id="textInput" value="">

8 Comments

but is there anyway to do it without javascript or jquery?
This is from mobile-web-app.blogspot.com/2012/03/… , still javascript. code<label for="rangeinput">Range</label> <input id="rangeinput" type="range" min="0" max="10" value="5" onchange="rangevalue.value=value"></input> <output id="rangevalue">5</output>
Does anyone else think that providing a blind slider is lacking. True that providing fancy widgets is not the role of the basic standard, but showing the selected value is core to this widget, so I think that (optionally) showing the number in a basic form such as a tooltip on top of the slider handle would make for a better design.
@BaselShishani Couldn't agree more, not really sure what the thought process behind that was.
@BaselShishani: According to MDN: "range: A control for entering a number whose exact value is not important.". In light of that assumption, showing no exact value makes sense. But in practice it will probably also be used for selecting exact values.
|
58

version with editable input:

<form>
  <input type="range" name="amountRange" min="0" max="20" value="0" oninput="this.form.amountInput.value=this.value" />
  <input type="number" name="amountInput" min="0" max="20" value="0" oninput="this.form.amountRange.value=this.value" />
</form>

http://jsfiddle.net/Xjxe6

2 Comments

Replace form variables with this.nextElementSibling or this.previousElementSibling and replace oninput with onchange to get a version that works outside of a form. jsfiddle.net/Xjxe6/94
fantastic answer!
40

an even better way would be to catch the input event on the input itself rather than on the whole form (performance wise) :

<input type="range" id="rangeInput" name="rangeInput" min="0" max="20" value="0"
       oninput="amount.value=rangeInput.value">                                                       

<output id="amount" name="amount" for="rangeInput">0</output>

Here's a fiddle (with the id added as per Ryan's comment).

3 Comments

In Firefox 27, this didn't work for me until I added id="amount" for the output, too.
this should work without id: oninput="this.form.amount.value=this.value"
this works but how do I get to current value and show it when the page refreshes? :-/
21

If you want your current value to be displayed beneath the slider and moving along with it, try this:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>MySliderValue</title>

</head>
<body>
  <h1>MySliderValue</h1>

  <div style="position:relative; margin:auto; width:90%">
    <span style="position:absolute; color:red; border:1px solid blue; min-width:100px;">
    <span id="myValue"></span>
    </span>
    <input type="range" id="myRange" max="1000" min="0" style="width:80%"> 
  </div>

  <script type="text/javascript" charset="utf-8">
var myRange = document.querySelector('#myRange');
var myValue = document.querySelector('#myValue');
var myUnits = 'myUnits';
var off = myRange.offsetWidth / (parseInt(myRange.max) - parseInt(myRange.min));
var px =  ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.offsetParent.offsetWidth / 2);

  myValue.parentElement.style.left = px + 'px';
  myValue.parentElement.style.top = myRange.offsetHeight + 'px';
  myValue.innerHTML = myRange.value + ' ' + myUnits;

  myRange.oninput =function(){
    let px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.offsetWidth / 2);
    myValue.innerHTML = myRange.value + ' ' + myUnits;
    myValue.parentElement.style.left = px + 'px';
  };
  </script>

</body>
</html>

Note that this type of HTML input element has one hidden feature, such as you can move the slider with left/right/down/up arrow keys when the element has focus on it. The same with Home/End/PageDown/PageUp keys.

Comments

19

Shortest version without form, min or external JavaScript.

<input type="range" value="0" max="10" oninput="num.value = this.value">
<output id="num">0</output>

Explanation

If you wanna retrieve the value from the output you commonly use an id that can be linked from the oninput instead of using this.nextElementSibling.value (we take advantage of something that we are already using)

Compare the example above with this valid but a little more complex and long answer:

<input id="num" type="range" value="0" max="100" oninput="this.nextElementSibling.value = this.value">
<output>0</output>

With the shortest answer:

  • We avoid the use of this, something weird in JS for newcomers
  • We avoid new concept about connecting siblings in the DOM
  • We avoid too much attributes in the input placing the id in the output

Notes

  • In both examples we don't need to add the min value when equal to 0
  • Removing JavaScript’s this keyword makes it a better language

1 Comment

Even better, value is displayed or can be set manually: <input type="range" class="custom-range" id="customRange22" value="50" min="0" max="100" oninput="num.value = this.value"> <input type="number" class="form-alternative ml-3" id="num" value="50" min="0" max="100" oninput="customRange22.value = this.value">
6

If you're using multiple slides, and you can use jQuery, you can do the follow to deal with multiple sliders easily:

function updateRangeInput(elem) {
  $(elem).next().val($(elem).val());
}
input { padding: 8px; border: 1px solid #ddd; color: #555; display: block; }
input[type=text] { width: 100px; }
input[type=range] { width: 400px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="range" min="0" max="100" oninput="updateRangeInput(this)" value="0">
<input type="text" value="0">

<input type="range" min="0" max="100" oninput="updateRangeInput(this)" value="50">
<input type="text" value="50">

Also, by using oninput on the <input type='range'> you'll receive events while dragging the range.

Comments

5

In plain JavaScript:

function displaySliderValue(eSlider){   
    eSlider.parentElement.querySelector('span').textContent = eSlider.value;
}
<div>
    <span>1</span><br>
    <input type="range" min="1" max="100" value="1" oninput="displaySliderValue(this);">
</div>

Comments

3

Here's a vanilla JS way of automatically adding the value to all range inputs without any extra HTML.

Edit: Chrome only. I didn't realize it doesn't work with Firefox.

document.querySelectorAll('input[type=range]').forEach(e => {
  e.setAttribute('data-value', e.value);
  e.addEventListener('input', () => {
    e.setAttribute('data-value', e.value);
  });
});
input[type="range"]::after {
  content: attr(data-value);
  margin-right: -50px;
  padding-left: 10px;
}
<input type="range"><br>
<input type="range"><br>
<input type="range">

Comments

1

I have a solution that involves (Vanilla) JavaScript, but only as a library. You habe to include it once and then all you need to do is set the appropriate source attribute of the number inputs.

The source attribute should be the querySelectorAll selector of the range input you want to listen to.

It even works with selectcs. And it works with multiple listeners. And it works in the other direction: change the number input and the range input will adjust. And it will work on elements added later onto the page (check https://codepen.io/HerrSerker/pen/JzaVQg for that)

Tested in Chrome, Firefox, Edge and IE11

;(function(){
  
  function emit(target, name) {
    var event
    if (document.createEvent) {
      event = document.createEvent("HTMLEvents");
      event.initEvent(name, true, true);
    } else {
      event = document.createEventObject();
      event.eventType = name;
    }

    event.eventName = name;

    if (document.createEvent) {
      target.dispatchEvent(event);
    } else {
      target.fireEvent("on" + event.eventType, event);
    }    
  }

  var outputsSelector = "input[type=number][source],select[source]";
  
  function onChange(e) {
    var outputs = document.querySelectorAll(outputsSelector)
    for (var index = 0; index < outputs.length; index++) {
      var item = outputs[index]
      var source = document.querySelector(item.getAttribute('source'));
      if (source) {
        if (item === e.target) {
          source.value = item.value
          emit(source, 'input')
          emit(source, 'change')
        }

        if (source === e.target) {
          item.value = source.value
        }
      }
    }
  }
  
  document.addEventListener('change', onChange)
  document.addEventListener('input', onChange)
}());
<div id="div">
  <input name="example" type="range" max="2250000" min="-200000" value="0" step="50000">
  <input id="example-value" type="number" max="2250000" min="-200000" value="0" step="50000" source="[name=example]">
  <br>

  <input name="example2" type="range" max="2240000" min="-160000" value="0" step="50000">
  <input type="number" max="2240000" min="-160000" value="0" step="50000" source="[name=example2]">
  <input type="number" max="2240000" min="-160000" value="0" step="50000" source="[name=example2]">
  <br>
  
  <input name="example3" type="range" max="20" min="0" value="10" step="1">
  <select source="[name=example3]">
    <option value="0">0</option>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
    <option value="6">6</option>
    <option value="7">7</option>
    <option value="8">8</option>
    <option value="9">9</option>
    <option value="10">10</option>
    <option value="11">11</option>
    <option value="12">12</option>
    <option value="13">13</option>
    <option value="14">14</option>
    <option value="15">15</option>
    <option value="16">16</option>
    <option value="17">17</option>
    <option value="18">18</option>
    <option value="19">19</option>
    <option value="20">20</option>
  </select>
  <br>
  
</div>
<br>

Comments

1

For people don't care about jquery use, here is a short way without using any id

<label> userAvatar :
  <input type="range" name="userAvatar" min="1" max="100" value="1"
         onchange="$('~ output', this).val(value)" 
         oninput="$('~ output', this).val(value)">
  <output>1</output>
</label>

Comments

1

Here's what I use to customize my range sliders

  • Use the <output> Element to show the current value
  • Use JS to read the min value max attributes values and convert to percentage
  • Move the Output element given that percentage
  • Show the current value using content: attr(data-value) attr(data-suffix) in a ::before pseudo-element.

Example:

const range = (elRange) => {
  const elInput = elRange.querySelector("input");
  const elTooltip = elRange.querySelector("output");
  const positionTooltip = () => {
    const val = elInput.valueAsNumber;
    const min = elInput.min ? Number(elInput.min) : 0;
    const max = elInput.max ? Number(elInput.max) : 100;
    const pos = (val - min) * 100 / (max - min);
    elTooltip.dataset.value = val;
    elRange.style.setProperty("--x", pos)
  };
  elInput.addEventListener("input", positionTooltip);
  positionTooltip();
};

document.querySelectorAll(".range").forEach(range);
:root {
  --color-accent: #0bb;
  --color-bg-2: #ddd;
  font: 1rem/1.4 system-ui, sans-serif;
}

.range {
  --x: 0;
  --size: 1rem;

  position: relative;
  touch-action: none;
  padding: 0.6rem 0;

  input {
    appearance: none;
    background: var(--color-bg-2);
    width: 100%;
    border-radius: 1rem;
    height: var(--size);
    border: 0;
    transition: transform 0.24s, box-shadow 0.24s, background 0.24s, color 0.24s;

    &::before,
    &::after {
      position: absolute;
      margin: 0 0.5rem;
      opacity: 0.5;
      top: 50%;
      translate: 0 -54%;
      font-size: 0.9em;
      z-index: 2;
    }

    &::before {
      content: attr(min);
    }

    &::after {
      content: attr(max);
      right: 0;
    }

    &:not(disabled) {
      cursor: pointer;
    }

    /* Webkit */
    &::-webkit-slider-thumb {
      appearance: none;
      height: var(--size);
      width: var(--size);
      background: var(--color-accent);
      border-radius: 1rem;
      box-shadow: none;
      border: none;
      position: relative;
      z-index: 1;
    }

    /* Firefox */
    &::-moz-range-thumb {
      appearance: none;
      height: var(--size);
      width: var(--size);
      background: var(--color-accent);
      border-radius: 1rem;
      box-shadow: none;
      border: none;
      position: relative;
      z-index: 1;
    }

    &:hover{
      background: color-mix(in srgb, var(--color-bg-2), #000 5%);
    }

    &:focus{
      +output {
        background-color: var(--color-accent);
        box-shadow: 0 0.1rem 0.3rem #0008;
        background: color-mix(in srgb, var(--color-accent), #fff 1%);

        .elevate & {
          transform: translateY(-1.8rem);
        }
      }
    }
  }

  output {
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 2;
    left: calc(var(--x) * 1% + 2px);
    top: calc(50% - 2px);
    padding: 0.4rem 0.5rem;
    height: var(--size);
    translate: calc(var(--x) * -1%) -50%;
    white-space: nowrap;
    background: var(--color-accent);
    color: #fff;
    border-radius: 0.5rem;
    pointer-events: none;
    transition: transform 0.24s, box-shadow 0.24s, background 0.24s, color 0.24s;

    &::before {
      content: attr(data-value) attr(data-suffix);
    }
  }
}
<div class="range">
  <input type="range" value="67">
  <output></output>
</div>

<div class="range elevate">
  <input type="range" value="999" min="500" max="1500">
  <output data-suffix=" $"></output>
</div>

<div class="range" style="width: 30cqi;">
  <input type="range" value="4" min="1" max="5">
  <output data-suffix="★"></output>
</div>

Comments

-1

Try This :

 <input min="0" max="100" id="when_change_range" type="range">
 <input type="text" id="text_for_show_range">

and in jQuery section :

 $('#when_change_range').change(function(){
 document.getElementById('text_for_show_range').value=$(this).val();
  });

1 Comment

Excellent !!! , but note that you put value='20' more than the max ='10' , so it gets an error .
-3

<form name="registrationForm">
    <input type="range" name="ageInputName" id="ageInputId" value="24" min="1" max="10" onchange="getvalor(this.value);" oninput="ageOutputId.value = ageInputId.value">
    <input type="text" name="ageOutputName" id="ageOutputId"></input>
</form>

1 Comment

Error: { "message": "Uncaught ReferenceError: getvalor is not defined", "filename": "stacksnippets.net/js", "lineno": 12, "colno": 169 }
-6

if you still looking for the answer you can use input type="number" in place of type="range" min max work if it set in that order:
1-name
2-maxlength
3-size
4-min
5-max
just copy it

<input  name="X" maxlength="3" size="2" min="1" max="100" type="number" />

1 Comment

This is just wrong, it does not do what the topic starter requested.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.