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

enter image description here

I want the left side to be green and the right side to be gray. As pictured above would be PERFECT. Preferably a pure CSS solution (only need to worry about WebKit).

Is such a thing possible?

This question is related to css html input webkit

The answer is


While the accepted answer is good in theory, it ignores the fact that the thumb then cannot be bigger than size of the track without being chopped off by the overflow: hidden. See this example of how to handle this with just a tiny bit of JS.

_x000D_
_x000D_
// .chrome styling Vanilla JS

document.getElementById("myinput").oninput = function() {
  var value = (this.value-this.min)/(this.max-this.min)*100
  this.style.background = 'linear-gradient(to right, #82CFD0 0%, #82CFD0 ' + value + '%, #fff ' + value + '%, white 100%)'
};
_x000D_
#myinput {
  background: linear-gradient(to right, #82CFD0 0%, #82CFD0 50%, #fff 50%, #fff 100%);
  border: solid 1px #82CFD0;
  border-radius: 8px;
  height: 7px;
  width: 356px;
  outline: none;
  transition: background 450ms ease-in;
  -webkit-appearance: none;
}
_x000D_
<div class="chrome">
  <input id="myinput" min="0" max="60" type="range" value="30" />
</div>
_x000D_
_x000D_
_x000D_


Yes, it is possible. Though I wouldn't recommend it because input range is not really supported properly by all browsers because is an new element added in HTML5 and HTML5 is only a draft (and will be for long) so going as far as to styling it is perhaps not the best choice.

Also, you'll need a bit of JavaScript too. I took the liberty of using jQuery library for this, for simplicity purposes.

Here you go: http://jsfiddle.net/JnrvG/1/.


The previous accepted solution is not working any longer.

I ended up coding a simple function which wraps the range into a styled container adding the bar that is needed before the cursor. I wrote this example where easy to see the two colors 'blue' and 'orange' set in the css, so they can be quickly modified.


If you use first answer, there is a problem with thumb. In chrome if you want the thumb to be larger than the track, then the box shadow overlaps the track with the height of the thumb.

Just sumup all these answers and wrote normally working slider with larger slider thumb: jsfiddle

_x000D_
_x000D_
const slider = document.getElementById("myinput")
const min = slider.min
const max = slider.max
const value = slider.value

slider.style.background = `linear-gradient(to right, red 0%, red ${(value-min)/(max-min)*100}%, #DEE2E6 ${(value-min)/(max-min)*100}%, #DEE2E6 100%)`

slider.oninput = function() {
  this.style.background = `linear-gradient(to right, red 0%, red ${(this.value-this.min)/(this.max-this.min)*100}%, #DEE2E6 ${(this.value-this.min)/(this.max-this.min)*100}%, #DEE2E6 100%)`
};
_x000D_
#myinput {
  border-radius: 8px;
  height: 4px;
  width: 150px;
  outline: none;
  -webkit-appearance: none;
}

input[type='range']::-webkit-slider-thumb {
  width: 6px;
  -webkit-appearance: none;
  height: 12px;
  background: black;
  border-radius: 2px;
}
_x000D_
<div class="chrome">
  <input id="myinput" type="range" min="0" value="25" max="200" />
</div>
_x000D_
_x000D_
_x000D_


It's now supported with pseudo elements in each of WebKit, Firefox and IE. But, of course, it's different in each one. : (

See this question's answers and/or search for a CodePen titled prettify <input type=range> #101 for some solutions.


A small update to this one:

if you use the following it will update on the fly rather than on mouse release.

"change mousemove", function"

<script>
$('input[type="range"]').on("change mousemove", function () {
    var val = ($(this).val() - $(this).attr('min')) / ($(this).attr('max') - $(this).attr('min'));

    $(this).css('background-image',
                '-webkit-gradient(linear, left top, right top, '
                + 'color-stop(' + val + ', #2f466b), '
                + 'color-stop(' + val + ', #d3d3db)'
                + ')'
                );
});</script>

input type="range" min="0" max="50" value="0"  style="margin-left: 6%;width: 88%;background-color: whitesmoke;"

above code changes range input style.....


Building on top of @dargue3's answer, if you want the thumb to be larger than the track, you want to fully take advantage of the <input type="range" /> element and go cross browser, you need a little extra lines of JS & CSS.

On Chrome/Mozilla you can use the linear-gradient technique, but you need to adjust the ratio based on the min, max, value attributes as mentioned here by @Attila O.. You need to make sure you are not applying this on Edge, otherwise the thumb is not displayed. @Geoffrey Lalloué explains this in more detail here.

Another thing worth mentioning, is that you need to adjust the rangeEl.style.height = "20px"; on IE/Older. Simply put this is because in this case "the height is not applied to the track but rather the whole input including the thumb". fiddle

_x000D_
_x000D_
/**_x000D_
 * Sniffs for Older Edge or IE,_x000D_
 * more info here:_x000D_
 * https://stackoverflow.com/q/31721250/3528132_x000D_
 */_x000D_
function isOlderEdgeOrIE() {_x000D_
  return (_x000D_
    window.navigator.userAgent.indexOf("MSIE ") > -1 ||_x000D_
    !!navigator.userAgent.match(/Trident.*rv\:11\./) ||_x000D_
    window.navigator.userAgent.indexOf("Edge") > -1_x000D_
  );_x000D_
}_x000D_
_x000D_
function valueTotalRatio(value, min, max) {_x000D_
  return ((value - min) / (max - min)).toFixed(2);_x000D_
}_x000D_
_x000D_
function getLinearGradientCSS(ratio, leftColor, rightColor) {_x000D_
  return [_x000D_
    '-webkit-gradient(',_x000D_
    'linear, ',_x000D_
    'left top, ',_x000D_
    'right top, ',_x000D_
    'color-stop(' + ratio + ', ' + leftColor + '), ',_x000D_
    'color-stop(' + ratio + ', ' + rightColor + ')',_x000D_
    ')'_x000D_
  ].join('');_x000D_
}_x000D_
_x000D_
function updateRangeEl(rangeEl) {_x000D_
  var ratio = valueTotalRatio(rangeEl.value, rangeEl.min, rangeEl.max);_x000D_
_x000D_
  rangeEl.style.backgroundImage = getLinearGradientCSS(ratio, '#919e4b', '#c5c5c5');_x000D_
}_x000D_
_x000D_
function initRangeEl() {_x000D_
  var rangeEl = document.querySelector('input[type=range]');_x000D_
  var textEl = document.querySelector('input[type=text]');_x000D_
_x000D_
  /**_x000D_
   * IE/Older Edge FIX_x000D_
   * On IE/Older Edge the height of the <input type="range" />_x000D_
   * is the whole element as oposed to Chrome/Moz_x000D_
   * where the height is applied to the track._x000D_
   *_x000D_
   */_x000D_
  if (isOlderEdgeOrIE()) {_x000D_
    rangeEl.style.height = "20px";_x000D_
    // IE 11/10 fires change instead of input_x000D_
    // https://stackoverflow.com/a/50887531/3528132_x000D_
    rangeEl.addEventListener("change", function(e) {_x000D_
      textEl.value = e.target.value;_x000D_
    });_x000D_
    rangeEl.addEventListener("input", function(e) {_x000D_
      textEl.value = e.target.value;_x000D_
    });_x000D_
  } else {_x000D_
    updateRangeEl(rangeEl);_x000D_
    rangeEl.addEventListener("input", function(e) {_x000D_
      updateRangeEl(e.target);_x000D_
      textEl.value = e.target.value;_x000D_
    });_x000D_
  }_x000D_
}_x000D_
_x000D_
initRangeEl();
_x000D_
input[type="range"] {_x000D_
  -webkit-appearance: none;_x000D_
  -moz-appearance: none;_x000D_
  width: 300px;_x000D_
  height: 5px;_x000D_
  padding: 0;_x000D_
  border-radius: 2px;_x000D_
  outline: none;_x000D_
  cursor: pointer;_x000D_
}_x000D_
_x000D_
_x000D_
/*Chrome thumb*/_x000D_
_x000D_
input[type="range"]::-webkit-slider-thumb {_x000D_
  -webkit-appearance: none;_x000D_
  -moz-appearance: none;_x000D_
  -webkit-border-radius: 5px;_x000D_
  /*16x16px adjusted to be same as 14x14px on moz*/_x000D_
  height: 16px;_x000D_
  width: 16px;_x000D_
  border-radius: 5px;_x000D_
  background: #e7e7e7;_x000D_
  border: 1px solid #c5c5c5;_x000D_
}_x000D_
_x000D_
_x000D_
/*Mozilla thumb*/_x000D_
_x000D_
input[type="range"]::-moz-range-thumb {_x000D_
  -webkit-appearance: none;_x000D_
  -moz-appearance: none;_x000D_
  -moz-border-radius: 5px;_x000D_
  height: 14px;_x000D_
  width: 14px;_x000D_
  border-radius: 5px;_x000D_
  background: #e7e7e7;_x000D_
  border: 1px solid #c5c5c5;_x000D_
}_x000D_
_x000D_
_x000D_
/*IE & Edge input*/_x000D_
_x000D_
input[type=range]::-ms-track {_x000D_
  width: 300px;_x000D_
  height: 6px;_x000D_
  /*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */_x000D_
  background: transparent;_x000D_
  /*leave room for the larger thumb to overflow with a transparent border */_x000D_
  border-color: transparent;_x000D_
  border-width: 2px 0;_x000D_
  /*remove default tick marks*/_x000D_
  color: transparent;_x000D_
}_x000D_
_x000D_
_x000D_
/*IE & Edge thumb*/_x000D_
_x000D_
input[type=range]::-ms-thumb {_x000D_
  height: 14px;_x000D_
  width: 14px;_x000D_
  border-radius: 5px;_x000D_
  background: #e7e7e7;_x000D_
  border: 1px solid #c5c5c5;_x000D_
}_x000D_
_x000D_
_x000D_
/*IE & Edge left side*/_x000D_
_x000D_
input[type=range]::-ms-fill-lower {_x000D_
  background: #919e4b;_x000D_
  border-radius: 2px;_x000D_
}_x000D_
_x000D_
_x000D_
/*IE & Edge right side*/_x000D_
_x000D_
input[type=range]::-ms-fill-upper {_x000D_
  background: #c5c5c5;_x000D_
  border-radius: 2px;_x000D_
}_x000D_
_x000D_
_x000D_
/*IE disable tooltip*/_x000D_
_x000D_
input[type=range]::-ms-tooltip {_x000D_
  display: none;_x000D_
}_x000D_
_x000D_
input[type="text"] {_x000D_
  border: none;_x000D_
}
_x000D_
<input type="range" value="80" min="10" max="100" step="1" />_x000D_
<input type="text" value="80" size="3" />
_x000D_
_x000D_
_x000D_


Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to input

Angular 4 - get input value React - clearing an input value after form submit Min and max value of input in angular4 application Disable Button in Angular 2 Angular2 - Input Field To Accept Only Numbers How to validate white spaces/empty spaces? [Angular 2] Can't bind to 'ngModel' since it isn't a known property of 'input' Mask for an Input to allow phone numbers? File upload from <input type="file"> Why does the html input with type "number" allow the letter 'e' to be entered in the field?

Examples related to webkit

com.apple.WebKit.WebContent drops 113 error: Could not find specified service HTML5 Video autoplay on iPhone What does the shrink-to-fit viewport meta attribute do? Chrome / Safari not filling 100% height of flex parent How to style HTML5 range input to have different color before and after slider? What are -moz- and -webkit-? Video auto play is not working in Safari and Chrome desktop browser Rotate and translate Background color not showing in print preview Blurry text after using CSS transform: scale(); in Chrome