7

Please take a look at the following CodePen. There you can see my custom range input. I want the tick positions of the slider to be shown and for that I added the datalist:

fieldset {
    border: 2px solid #48530D;
    padding-top: 27px;
        padding-right: 20px;
        padding-bottom: 0px;
        padding-left: 20px;
}

input[type=range] {
    -webkit-appearance: none;
    width: 100%;
    margin: 4px 0;
}

input[type=range]:focus {
    outline: none;
}

input[type=range]::-webkit-slider-runnable-track {
    width: 100%;
    height: 8px;
    cursor: pointer;
    box-shadow: 0px 0px 0px rgba(0, 0, 0, 0), 0px 0px 0px rgba(13, 13, 13, 0);
    background: #a4b162;
    border-radius: 0px;
    border: 1px solid rgba(0, 0, 0, 0);
}

input[type=range]::-webkit-slider-thumb {
    box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
    border: 1px solid #000000;
    height: 16px;
    width: 16px;
    border-radius: 0px;
    background: #48530d;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -5px;
}

input[type=range]:focus::-webkit-slider-runnable-track {
    background: #a6b365;
}

input[type=range]::-moz-range-track {
    width: 100%;
    height: 8px;
    cursor: pointer;
    box-shadow: 0px 0px 0px rgba(0, 0, 0, 0), 0px 0px 0px rgba(13, 13, 13, 0);
    background: #a4b162;
    border-radius: 0px;
    border: 1px solid rgba(0, 0, 0, 0);
}

input[type=range]::-moz-range-thumb {
    box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
    border: 1px solid #000000;
    height: 16px;
    width: 16px;
    border-radius: 0px;
    background: #48530d;
    cursor: pointer;
}

input[type=range]::-ms-track {
    width: 100%;
    height: 8px;
    cursor: pointer;
    background: transparent;
    border-color: transparent;
    color: transparent;
}

input[type=range]::-ms-fill-lower {
    background: #a2af5f;
     border: 1px solid rgba(0, 0, 0, 0);
     border-radius: 0px;
     box-shadow: 0px 0px 0px rgba(0, 0, 0, 0), 0px 0px 0px rgba(13, 13, 13, 0);
}

input[type=range]::-ms-fill-upper {
    background: #a4b162;
    border: 1px solid rgba(0, 0, 0, 0);
    border-radius: 0px;
    box-shadow: 0px 0px 0px rgba(0, 0, 0, 0), 0px 0px 0px rgba(13, 13, 13, 0);
}

input[type=range]::-ms-thumb {
    box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
    border: 1px solid #000000;
    height: 16px;
    width: 16px;
    border-radius: 0px;
    background: #48530d;
    cursor: pointer;
    height: 8px;
}

input[type=range]:focus::-ms-fill-lower {
    background: #a4b162;
}

input[type=range]:focus::-ms-fill-upper {
    background: #a6b365;
}
<fieldset>
    <form>
        <input max="6" min="1" step="1" name="question_three" type="range" list="question_three_list" />
        <datalist id="question_three_list">
            <option>1</option>
            <option>2</option>
            <option>3</option>
            <option>4</option>
            <option>5</option>
            <option>6</option>
        </datalist>
    </form>
</fieldset>

But unfortunately nothing is showing up. What I wanted to achieve is the following (ugly example created in MS Paint, but I guess you will get what I mean):

Example image

So how can I achieve that?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Mulgard
  • 9,877
  • 34
  • 129
  • 232

3 Answers3

36

I know my answer is way way late, but I keep coming back here when I try to find doing the same thing. I did manage to display tickmarks using the following settings.

The code results in the following: Displaying range ticks for input range slider

* {
  box-sizing: border-box;
}

.slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 25px;
  background: #D3D3D3;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
}

.slider:hover {
  opacity: 1;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  background: #FF0000;
  cursor: pointer;
}

.slider::-moz-range-thumb {
  width: 25px;
  height: 25px;
  background: #FF0000;
  cursor: pointer;
}

.sliderticks {
  display: flex;
  justify-content: space-between;
  padding: 0 10px;
}

.sliderticks p {
  position: relative;
  display: flex;
  justify-content: center;
  text-align: center;
  width: 1px;
  background: #D3D3D3;
  height: 10px;
  line-height: 40px;
  margin: 0 0 20px 0;
}
<div class="range">
  <input type="range" min="0" max="5" value="2" class="slider">
  <div class="sliderticks">
    <p>0</p>
    <p>1</p>
    <p>2</p>
    <p>3</p>
    <p>4</p>
    <p>5</p>
  </div>
</div>
DoubleYou
  • 1,057
  • 11
  • 25
  • 2
    This is a great workaround. Instead of hardcoding the values inside your `

    ` How would you dynamically `map()` and generate values based on the input `min`, `max` and `step`?

    – Null isTrue Jan 29 '20 at 16:17
  • To be honest, I often have a server-side script (e.g. PHP) generating the values for me. I can imagine giving each an ID and using Javascript would also work. – DoubleYou Feb 02 '20 at 12:16
  • In the example, HTML script, the JSX element 'input' has no corresponding closing tag. The closing tag "/" is needed. – Err Dec 14 '22 at 22:33
3
-webkit-appearance: none;

The above removes platform-native styling (Chrome / Safari), which removes the ticks.

You can get more information here, but unfortunately, styling support for input ranges (particularly ticks) is still pretty terrible.

Community
  • 1
  • 1
Marc DePoe
  • 43
  • 6
2

document.querySelectorAll(".__range-step").forEach(function(ctrl) {
 var el = ctrl.querySelector('input');        
 var output = ctrl.querySelector('output'); 
 var newPoint, newPlace, offset;
 el.oninput =function(){ 
  // colorize step options
  ctrl.querySelectorAll("option").forEach(function(opt) {
   if(opt.value<=el.valueAsNumber)                
    opt.style.backgroundColor = '#48530d';
   else
    opt.style.backgroundColor = '#a4b162';
  });           
 };
 el.oninput();    
});
.__range input
{
  outline: none;
 -webkit-appearance: none;
 background-color: #aaa;
 height: 3px;
 width: 100%;
 margin: 10px auto;
}
input[type=range]::-webkit-slider-runnable-track {
    width: 100%;
    height: 8px;
    cursor: pointer;
    box-shadow: 0px 0px 0px rgba(0, 0, 0, 0), 0px 0px 0px rgba(13, 13, 13, 0);
    background: #a4b162;
    border-radius: 0px;
    border: 1px solid rgba(0, 0, 0, 0);
}
input[type=range]::-webkit-slider-thumb {
    box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
    border: 1px solid #000000;
    height: 16px;
    width: 16px;
    border-radius: 0px;
    background: #48530d;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -5px;
}

.__range-step{
 position: relative;                
}

.__range-max{
 float: right;
}
.__range-step datalist {
 position:relative;
 display: flex;
 justify-content: space-between;
 height: auto;
 bottom: 16px;
 /* disable text selection */
 -webkit-user-select: none; /* Safari */        
 -moz-user-select: none; /* Firefox */
 -ms-user-select: none; /* IE10+/Edge */                
 user-select: none; /* Standard */
 /* disable click events */
 pointer-events:none;  
}
.__range-step datalist option {
 width: 10px;
 height: 10px;
 min-height: 10px;
  padding:0;
  line-height: 40px;
}

.__range{
  margin:10px 40px;
}
<div class="__range">
      <input value="4" type="range" max="6" min="1" step="1" list="ticks1">
</div>

<div class="__range __range-step">
        <input value="4" type="range" max="6" min="1" step="1" list="ticks1">
        <datalist id="ticks1">
            <option>1</option>
            <option>2</option>
            <option>3</option>
            <option>4</option>
            <option>5</option>
            <option>6</option>
        </datalist>
</div>
n.y
  • 3,343
  • 3
  • 35
  • 54