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">  
Community
  • 1
  • 1
Ben Cook
  • 1,654
  • 2
  • 18
  • 32

6 Answers6

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

Ben Cook
  • 1,654
  • 2
  • 18
  • 32
Alexander Dayan
  • 2,846
  • 1
  • 17
  • 30
  • 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 Feb 02 '15 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: http://codepen.io/ryanttb/pen/fHyEJ – Alexander Dayan Feb 02 '15 at 18:39
  • Very nice. Thank you. – Ben Cook Feb 02 '15 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 Jan 08 '23 at 00:59
  • Here is an example: https://jsfiddle.net/Allasso/egwmnf10/51/ . It also shows that you can do this on `` which gives a cool (IMO) representation of a number input. – KevinHJ Jan 08 '23 at 01: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.

Community
  • 1
  • 1
Wilson F
  • 1,250
  • 1
  • 20
  • 37
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

Duplich
  • 371
  • 3
  • 4
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)

Eric D'Souza
  • 680
  • 5
  • 21
  • 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. – V. Rubinetti Sep 18 '18 at 02: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>
mickeymicks
  • 637
  • 8
  • 13
0

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

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
dannyk3941
  • 13
  • 4
  • 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 Jan 08 '23 at 11:18