Style Lower and Upper Fill in HTML5 Range Input

Style lower and upper fill in HTML5 range input

First of all, read the article Styling Cross-Browser Compatible Range Inputs with CSS by Daniel Stern. His idea is to make the input invisible and then apply the custom styles.

He also developed an excellent online tool named randge.css in which you select the style preset and parameters and get auto generated CSS code like the following one:

input[type=range] {  -webkit-appearance: none;  margin: 10px 0;  width: 100%;}input[type=range]:focus {  outline: none;}input[type=range]::-webkit-slider-runnable-track {  width: 100%;  height: 12.8px;  cursor: pointer;  animate: 0.2s;  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;  background: #ac51b5;  border-radius: 25px;  border: 0px solid #000101;}input[type=range]::-webkit-slider-thumb {  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;  border: 0px solid #000000;  height: 20px;  width: 39px;  border-radius: 7px;  background: #65001c;  cursor: pointer;  -webkit-appearance: none;  margin-top: -3.6px;}input[type=range]:focus::-webkit-slider-runnable-track {  background: #ac51b5;}input[type=range]::-moz-range-track {  width: 100%;  height: 12.8px;  cursor: pointer;  animate: 0.2s;  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;  background: #ac51b5;  border-radius: 25px;  border: 0px solid #000101;}input[type=range]::-moz-range-thumb {  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;  border: 0px solid #000000;  height: 20px;  width: 39px;  border-radius: 7px;  background: #65001c;  cursor: pointer;}input[type=range]::-ms-track {  width: 100%;  height: 12.8px;  cursor: pointer;  animate: 0.2s;  background: transparent;  border-color: transparent;  border-width: 39px 0;  color: transparent;}input[type=range]::-ms-fill-lower {  background: #ac51b5;  border: 0px solid #000101;  border-radius: 50px;  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;}input[type=range]::-ms-fill-upper {  background: #ac51b5;  border: 0px solid #000101;  border-radius: 50px;  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;}input[type=range]::-ms-thumb {  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;  border: 0px solid #000000;  height: 20px;  width: 39px;  border-radius: 7px;  background: #65001c;  cursor: pointer;}input[type=range]:focus::-ms-fill-lower {  background: #ac51b5;}input[type=range]:focus::-ms-fill-upper {  background: #ac51b5;}
body { padding: 30px;}
<input type="range">

Applying Lower/Upper Fill to an input range with Min and Max Values in Chrome

We can give the slider a gradient background. Then all we need to do is calculate how much of the input needs to be filled in. The example below can handle all kinds of range values, not just from 1 till 5.

I also changed the colors to match your example.

const slider = document.querySelector(".range");

const adjustSlider = () => {
const min = slider.min;
const max = slider.max;
// Calculate visible width
const val = ((slider.value - min) * 100) / (max - min);

// Change these variables to the colors you need
const fillLeft = "#01c1c6";
const fillRight = "#d4f5f6";

slider.style.background = `linear-gradient(to right, ${fillLeft} ${val}%, ${fillRight} ${val}%`;
};

// Change background if input changes
slider.addEventListener("input", adjustSlider);

// We need to execute it at the start to set the initial value
adjustSlider();
.range{
width:96px;
-webkit-appearance:none;
background-color:transparent;
}
.range:focus{
outline:none;
}
.range::-webkit-slider-thumb{
-webkit-appearance:none;
display:inline-block;
width:14px;
height:14px;
background-color:#01c1c6;
border-radius:50%;
position:relative;
bottom:6px;
cursor:pointer;
}

.range::-webkit-slider-runnable-track {
width:100%;
height: 3px;
border: none;
cursor:pointer;
}
<div>
<input type="range" step="1" min="1" max="5" class="range">
</div>

How to style HTML5 range input to have different color before and after slider?

Pure CSS solution:

  • Chrome: Hide the overflow from input[range], and fill all the space left to
    thumb with shadow color.
  • IE: no need to reinvent the wheel: ::-ms-fill-lower
  • Firefox no need to reinvent the wheel: ::-moz-range-progress

/*Chrome*/@media screen and (-webkit-min-device-pixel-ratio:0) {    input[type='range'] {      overflow: hidden;      width: 80px;      -webkit-appearance: none;      background-color: #9a905d;    }        input[type='range']::-webkit-slider-runnable-track {      height: 10px;      -webkit-appearance: none;      color: #13bba4;      margin-top: -1px;    }        input[type='range']::-webkit-slider-thumb {      width: 10px;      -webkit-appearance: none;      height: 10px;      cursor: ew-resize;      background: #434343;      box-shadow: -80px 0 0 80px #43e5f7;    }
}/** FF*/input[type="range"]::-moz-range-progress { background-color: #43e5f7; }input[type="range"]::-moz-range-track { background-color: #9a905d;}/* IE*/input[type="range"]::-ms-fill-lower { background-color: #43e5f7; }input[type="range"]::-ms-fill-upper { background-color: #9a905d;}
<input type="range"/>

How to fill HTML5 input[type=range] on the left side of the thumb with CSS only?

Sorry! I've found the answer 20 minutes after posting this... I was searching for that all day long...
Here's the answer:

Use the ::-moz-range-progress element!

Example (works for the snippet)

input[type="range"].slider-track::-moz-range-progress {
background: red;
}

Is it possible to style input type=range with just a left and right color and no thumb?

Here is a working example.

function sliderValueChange(e) {
console.log(e.value);
}
:root {
--slider-width: 300px;
--slider-height: 20px;
}

input[type='range'] {
cursor: ew-resize;
overflow: hidden;
}

@media screen and (-webkit-min-device-pixel-ratio:0) {
input[type='range'] {
width: var(--slider-width);
-webkit-appearance: none;
background-color: #353535;
}
input[type='range']::-webkit-slider-runnable-track {
height: var(--slider-height);
-webkit-appearance: none;
color: #13bba4;
margin-top: -1px;
}
input[type='range']::-webkit-slider-thumb {
width: 0px;
-webkit-appearance: none;
height: var(--slider-height);
box-shadow: calc(-1 * var(--slider-width)) 0 0 var(--slider-width) #43e5f7;
}
}

/* FF */
input[type="range"]::-moz-range-progress {
background-color: #43e5f7;
}
input[type="range"]::-moz-range-thumb {
height: var(--slider-height);
width: 0;
border: none;
box-shadow: calc(-1 * var(--slider-width)) 0 0 var(--slider-width) #43e5f7;
box-sizing: border-box;
}

/* IE */
input[type="range"]::-ms-fill-lower {
background-color: #43e5f7;
}
input[type="range"]::-ms-fill-upper {
background-color: #13bba4;
}
<input type="range" onchange="sliderValueChange(this)">

Styling input range for webkit with pure CSS

Interesting approach being used by the Ionic framework for styling the range input track with just CSS. They are adding a ::before pseudo-element to the ::-webkit-slider-thumb, making it as wide as possible and then positioning it on top of the track. (I couldn't get border-radius to work with it.)

input[type='range'] {  width: 210px;  height: 30px;  overflow: hidden;  cursor: pointer;}input[type='range'],input[type='range']::-webkit-slider-runnable-track,input[type='range']::-webkit-slider-thumb {  -webkit-appearance: none;}input[type='range']::-webkit-slider-runnable-track {  width: 200px;  height: 10px;  background: #AAA;}input[type='range']::-webkit-slider-thumb {  position: relative;  height: 30px;  width: 30px;  margin-top: -10px;  background: steelblue;  border-radius: 50%;  border: 2px solid white;}input[type='range']::-webkit-slider-thumb::before {  position: absolute;  content: '';  height: 10px; /* equal to height of runnable track */  width: 500px; /* make this bigger than the widest range input element */  left: -502px; /* this should be -2px - width */  top: 8px; /* don't change this */  background: #777;}
<div class="container">  <input type="range" min="0" max="100" value="10" /></div>

How to customize the HTML5 input range type looks using CSS?

EDIT: nowadays all major browser support both

  • <progress>

  • input[type='range']

Hence you should use one of these two, as explained in other answers, and this should not be the accepted answer anymore.


The <input type="range"> is pretty new and you are already attempting to customize it with CSS. :)

I wouldn't try that for two reasons:

  1. there might be huge compatibility issues now and for the next few (or many) years.
    Think that in nowadays a form control like <select> (available since the web started) is still problematic to be customized with CSS in a cross browser way. For instance if you set a padding for the select boxes, many browser (IE7, OPERA9, CHROME5, SAFARI4) will totally ignore the padding.
    It works only IE8 and on FF 3.6. (all tests done with HTML5 DOCTYPE so in standard mode).

  2. The <input type="range"> has been created to show a slider NOT a progress bar, attempting to cheat on it with CSS in order to transform a slider into progress bar it sounds bizarre. Like trying to use CSS to change a <textarea> into a table, but why don't you simply use a <table> to render tables?!

To show a progress bar in HTML5 you should follow the suggestion given by marcgg in his answer. Since no browser is currently rendereing it you could use a simple div with a p inside like this:

<div id="progress" style="position:relative; width:100px; height:20px; border:1px solid #cccccc;">
<p style="position:absolute; left:0; top:0; background-color:#0000ff; height:100%; width:30%; font-size:0px;"> </p>
</div>

Then simply update the style.width of inner P element in percent like:

width: 75%

FYI: if you want to do that in simple JS here is the code:

document.getElementById('progress').(getElementsByTagName('p')[0]).style.width = '75%';


Related Topics



Leave a reply



Submit