Style lower and upper fill in HTML5 range input
Solution 1
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">
Yes, with CSS only it's possible on IE only, but if you don't mind to add some scripting it can be simulated with linear gradient. See the following sample: codepen.io/ryanttb/pen/fHyEJ
Solution 2
There's a (newish?) pseudo-element for Firefox that styles (what IE calls) the 'lower' part of the range input. According to the documentation:
The ::-moz-range-progress CSS pseudo-element represents the portion of the "track" (the groove in which the indicator aka thumb slides) of an
<input>
of type="range", which corresponds to values lower than the value currently selected by the thumb.
For the upper track, you still use (per Alexander Dayan's answer) ::-moz-range-track
.
I just discovered and tried it today; works pretty well.
Solution 3
At this stage there is still no option for native implementation of
-ms-fill-lower
or -moz-fill-lower
in Chrome. Manipulating the range input element with RangeSlider.js was not an option so I used the tweaking technique with CSS linear Gradients and little bit of javascript to fire css changes on input range thumb movement
Hope this helps someone check example on Codepen
Solution 4
I'm using this solution inspired by Noah Blon. It uses a box shadow based on view width (100vw is the max width of the slider), and constrains with overflow:hidden. I'm using a round thumb, so subtracted half the thumb width from the 100vw, otherwise the box shadow creeps over the other side of the thumb.
css
.wb-PKR-slider {
-webkit-appearance:none;
appearance:none;
margin:5px;
width:calc(100% - 10px);
width:-webkit-calc(100% - 10px);
height:25px;
outline:none;
background:bisque;
border-radius:12px;
overflow: hidden;
}
.wb-PKR-slider::-webkit-slider-thumb {
-webkit-appearance:none;
appearance:none;
width:25px;
height:25px;
background:sienna;
box-shadow: -100vw 0 0 calc(100vw - 12px) peru;
cursor:pointer;
border-radius: 50%;
}
html
<input type="range" min="0" max="150" value="25" class="wb-PKR-slider" id="wb-PKR-chip-count">
(fyi bisque, sienna and peru are all named css colours)
Solution 5
i'm using the following code which was based on the link provided by A. Dayan. Taking note of the min-max values and being specifically for webkit, also hiding that it is actually a gradient.
<html>
<head>
<title>A styled slider</title>
<script src="js/jquery-1.10.2.min.js" type="text/javascript"></script>
<style type="text/css">
input[type='range'] {
-webkit-appearance: none;
width: 100%;
border-radius: 4px;
height: 5px;
border-color: #1f1f1f;
border-style: solid;
border-width: 1px;
background: -webkit-linear-gradient(left, green 0%, green 50%, black 50%);
}
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none !important;
-webkit-border-radius: 2px;
background-color: blue;
height: 21px;
width: 9px;
}
input[type=range]:focus {
outline: none;
}
</style>
</head>
<body>
<div>
<input type="range" value="75" min="100" max="300" />
</div>
<script type="text/javascript" >
$('input[type="range"]').on('input', function () {
var percent = Math.ceil(((this.value - this.min) / (this.max - this.min)) * 100);
console.log(this.min);
$(this).css('background', '-webkit-linear-gradient(left, green 0%, green ' + percent + '%, black ' + percent + '%)');
});
</script>
</body>
</html>
Ben Cook
I'm an energetic manager who loves coaching ambitious software engineers and fast-paced, Agile development teams. Formerly, I was a software engineer, educator, published author, student of ancient political philosophy, and Peace Corps volunteer. I have strong communication and team leadership skills and a history of building relationships of trust and frankness with employees and coworkers.
Updated on August 21, 2020Comments
-
Ben Cook over 3 years
As explained here, IE allows styling of the lower and upper fill or track regions in CSS as follows:
/* The following only affects the range input in IE */ input[type="range"]::-ms-fill-lower { background-color: red; } input[type="range"]::-ms-fill-upper { background-color: blue; }
<input type="range">
Does anyone know of a way to apply different styles to the upper and lower tracks of a range input in Firefox, Chrome, etc. using CSS or any JS library?
UPDATE:
As pointed out by Wilson F, this is now supported in Firefox:
/* The following only affects the range input in FF */ input[type="range"]::-moz-range-progress { background-color: red; } input[type="range"]::-moz-range-track { background-color: blue; }
<input type="range">
-
Ben Cook about 9 yearsthank you. This is very helpful, but unfortunately, it doesn't answer my main question. I want to apply different styles to the regions of the track to the left and to the right of the "thumb". I'm not sure if this is possible outside of IE.
-
Alexander Dayan about 9 yearsYes, with CSS only it's possible on IE only, but if you don't mind to add some scripting it can be simulated with linear gradient. See the following sample: codepen.io/ryanttb/pen/fHyEJ
-
Ben Cook about 9 yearsVery nice. Thank you.
-
Milad Rahimi about 8 yearsIt just shows how to set color for the range not lower and upper as mentioned in the question
-
user3162879 about 6 yearsCan I get the AngularJS version please?
-
Duplich almost 6 yearsUnfortunately I have no more access to this code. It is left behind in the old company I did this for :/
-
V. Rubinetti over 5 yearsThis is a good css-only solution, even if it feels very hack-y. Note that on the lower portion of the slider, the fill color will be cutoff in a rectangular fashion, so this will not work if you want your track to have a border radius.
-
graup over 3 yearsThis is a great trick. You can also use CSS variables to set the value in a more efficient way.