34

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">  

6 Answers 6

14

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

6
  • 3
    thank 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.
    – Ben Cook
    Commented Feb 2, 2015 at 18:05
  • 1
    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 Commented Feb 2, 2015 at 18:39
  • Very nice. Thank you.
    – Ben Cook
    Commented Feb 2, 2015 at 18:50
  • Regarding the using linear gradient (the last codepen example) if you want to have a solid color in each region (instead of a gradient appearance) use background: linear-gradient(to right, blue, blue 50%, green 50%, green). This will make it solid blue on the left, and solid green on the right.
    – KevinHJ
    Commented Jan 8, 2023 at 0:59
  • Here is an example: jsfiddle.net/Allasso/egwmnf10/51 . It also shows that you can do this on <input type="number"> which gives a cool (IMO) representation of a number input.
    – KevinHJ
    Commented Jan 8, 2023 at 1:54
10

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.

6

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

3
  • 1
    Can I get the AngularJS version please? Commented Apr 12, 2018 at 6:16
  • Unfortunately I have no more access to this code. It is left behind in the old company I did this for :/
    – Duplich
    Commented Apr 24, 2018 at 12:29
  • This is a great trick. You can also use CSS variables to set the value in a more efficient way.
    – graup
    Commented Oct 26, 2020 at 3:17
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)

1
  • This 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. Commented Sep 18, 2018 at 2:37
1

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>
1
  • 1
    It just shows how to set color for the range not lower and upper as mentioned in the question Commented Apr 7, 2016 at 14:11
0

There is a CSS property accent-color that will style the lower fill portion of the input[type="range"] element in Chrome.

1
  • Note that this will only allow styling the lower portion. Any attempt to style the upper portion eg using -webkit-slider-runnable-track will wipe it out.
    – KevinHJ
    Commented Jan 8, 2023 at 11:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.