3

I'm currently styling HTML5 input type range using below code:

input[type="range"]{
    -webkit-appearance: none;
    -moz-apperance: none;
    width: 100%;
    height: 8px;
    padding: 0 20px;
    background: #024069;
    border-radius: 2px;
    margin-top: 25px;
}


input[type="range"]::-webkit-slider-thumb{
    -webkit-appearance:none; 
    -moz-apperance:none; 
    width:25px; 
    height:25px;
    -webkit-border-radius:20px; 
    -moz-border-radius:20px; 
    -ms-border-radius:20px; 
    -o-border-radius:20px; 
    border-radius:20px;
    background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fefefe), color-stop(0.49, #d7d7d7), color-stop(0.51, #d1d1d1), color-stop(1, #c8c8c8) );
    border: 1px solid #787878;
}

This is all good. But now I'm trying to have two different colours on the actual slider so left of the thumb is blue and right of the thumb is black.

I tried :before but it didn't work. How can we achieve this?

Passionate Engineer
  • 10,034
  • 26
  • 96
  • 168

3 Answers3

11

Here's some JavaScript that updates the colour of the bar when you change the value.

input.oninput = function () {
  var value = (input.value - input.min)/(input.max - input.min);
  input.style.backgroundImage = [
    '-webkit-gradient(',
      'linear, ',
      'left top, ',
      'right top, ',
      'color-stop(' + value + ', blue), ',
      'color-stop(' + value + ', red)',
    ')'
  ].join('');
};

onload = function() {
  var inputs = document.querySelectorAll('input[type=range]');
  for (var i = 0; i < inputs.length; i++) {
    input = inputs[i]
    input.oninput = function () {
      var value = (input.value - input.min)/(input.max - input.min);
      input.style.backgroundImage = [
        '-webkit-gradient(',
          'linear, ',
          'left top, ',
          'right top, ',
          'color-stop(' + value + ', blue), ',
          'color-stop(' + value + ', red)',
        ')'
      ].join('');
    };
  }
};
body {
    margin: 20px;
}
input[type="range"]{
    -webkit-appearance: none;
    -moz-apperance: none;
    width: 200px;
    height: 8px;
    padding: 0;
    border-left: 20px solid blue;
    border-right: 20px solid red;
    background: #024069;
    border-radius: 2px;
    margin-top: 25px;
    background-image: -webkit-gradient(
        linear,
        left top,
        right top,
        color-stop(0.2, blue),
        color-stop(0.2, red)
    );
    outline: none;
}


input[type="range"]::-webkit-slider-thumb{
    -webkit-appearance:none; 
    -moz-apperance:none; 
    width:25px; 
    height:25px;
    -webkit-border-radius:20px; 
    -moz-border-radius:20px; 
    -ms-border-radius:20px; 
    -o-border-radius:20px; 
    border-radius:20px;
    background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fefefe), color-stop(0.49, #d7d7d7), color-stop(0.51, #d1d1d1), color-stop(1, #c8c8c8) );
    border: 1px solid #787878;
}
<!doctype html>
<html>
  <body>
    <input type="range" min="1" max="100" step="1" value="20">
  </body>
</html>

Thanks to @adamvert for suggesting to use oninput instead of onchange.

Attila O.
  • 15,659
  • 11
  • 54
  • 84
  • 3
    Very nice, but you need to use oninput instead of onchange so that the background updates as you drag the thumb – adamvert Sep 23 '14 at 10:19
  • could you provide React version of this on codesandbox ? here similar question : https://stackoverflow.com/questions/71751563/making-input-thumb-bigger-than-rest/71765592#71765592 – walee Apr 06 '22 at 15:52
2

You'll need JS to do this the way you need. I assume you need the bar-coloring to work correctly even when you slide the thing. i.e. blue to the left and black to the right of the thumb.

Check this demo: http://fiddle.jshell.net/tv3bx/2/

Code:

function colorTheBar(slider) {
    var left = $('.left'), right = $('.right');
    console.log(slider.val());
    if(left.length == 0) {
        left = $('<div>').addClass('left').appendTo('body');
        right = $('<div>').addClass('right').appendTo('body');
    }
    left.css({
        left: (slider.offset().left + 20) + 'px',
        top: slider.offset().top + 'px',
        width: (slider.width() * (parseInt(slider.val())/100)) + 'px',
        height: slider.height() + 'px'
    });
    right.css({
        left: (slider.offset().left + 20 + slider.width() * (parseInt(slider.val())/100)) + 'px',
        top: slider.offset().top + 'px',
        width: (slider.width() * (1 - parseInt(slider.val())/100)) + 'px',
        height: slider.height() + 'px'
    });
}

$('input').change(function() {
    colorTheBar($(this));
});

colorTheBar($('input'));
​


/* CSS */

.left, .right {
    position: absolute;    
    z-index: 1;
}
.left {
    background-color: blue;
}
.right {
    background-color: black;
}
techfoobar
  • 65,616
  • 14
  • 114
  • 135
1

The easiest way do that is to use gradients:

CSS

input[type="range"]{
    -webkit-appearance: none;
    -moz-apperance: none;
    width: 100%;
    height: 8px;
    padding: 0 20px;
    background: #0000ff;
    background: -moz-linear-gradient(left,  #0000ff 0%, #0000ff 50%, #000000 50%, #000000 100%);
    background: -webkit-gradient(linear, left top, right top, color-stop(0%,#0000ff), color-stop(50%,#0000ff), color-stop(50%,#000000), color-stop(100%,#000000));
    background: -webkit-linear-gradient(left,  #0000ff 0%,#0000ff 50%,#000000 50%,#000000 100%);
    background: -o-linear-gradient(left,  #0000ff 0%,#0000ff 50%,#000000 50%,#000000 100%);
    background: -ms-linear-gradient(left,  #0000ff 0%,#0000ff 50%,#000000 50%,#000000 100%);
    background: linear-gradient(to right,  #0000ff 0%,#0000ff 50%,#000000 50%,#000000 100%);
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0000ff', endColorstr='#000000',GradientType=1 );
    border-radius: 2px;
    margin-top: 25px;
}


input[type="range"]::-webkit-slider-thumb{
    -webkit-appearance:none; 
    -moz-apperance:none; 
    width:25px; 
    height:25px;
    -webkit-border-radius:20px; 
    -moz-border-radius:20px; 
    -ms-border-radius:20px; 
    -o-border-radius:20px; 
    border-radius:20px;
    background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fefefe), color-stop(0.49, #d7d7d7), color-stop(0.51, #d1d1d1), color-stop(1, #c8c8c8) );
    border: 1px solid #787878;
}

To customize the gradient i recommend Ultimate CSS Gradient Generator.

Fiddle

yckart
  • 32,460
  • 9
  • 122
  • 129