Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Styling input range for webkit with pure CSS

I would like to customize input type range like this.

enter image description here

I tried to use the following code to change the thumb and as below but selected range color is not changed.

HTML:

<input type="range" />

CSS:

input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  height: 20px;
  width: 20px;
  border-radius: 10px;
  background: red;
  cursor: pointer;
  border: none;
  margin-top: -8px;
}

input[type=range] {
  -webkit-appearance: none;
  outline: 0;
  margin: 0;
  padding: 0;
  height: 30px;
  width: 100%;
}

Could anybody please suggest me to change the selected runnable track background color?

like image 802
Ponmalar Avatar asked Jan 18 '16 08:01

Ponmalar


People also ask

How do you style input type range in CSS?

To style the range input with CSS you'll need to apply styles to two pseudo-elements: ::-webkit-slider-thumb and ::-webkit-slider-runnable-track . Find out how you can apply custom styling and make the range input more functional and appealing. Contents of the article: CSS selectors for the range input.

How do I change the color of my input slider?

If the general appearance of the slider is fine, but the default blue color (in Chrome) needs to fit a theme color, apply a filter: hue-rotate(); to the input[type="range"] element. Other filters can be used. Some even change the background color of the slider. Save this answer.

Can I use webkit slider thumb?

::-webkit-slider-thumb Non-standard: This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

How do you enter range in HTML?

The <input type="range"> defines a control for entering a number whose exact value is not important (like a slider control). Default range is 0 to 100. However, you can set restrictions on what numbers are accepted with the attributes below. Tip: Always add the <label> tag for best accessibility practices!


2 Answers

I got a solution that does not use a style tag but css variable:

const input = document.querySelector("input");

function setBackgroundSize(input) {
  input.style.setProperty("--background-size", `${getBackgroundSize(input)}%`);
}

setBackgroundSize(input);

input.addEventListener("input", () => setBackgroundSize(input));

function getBackgroundSize(input) {
  const min = +input.min || 0;
  const max = +input.max || 100;
  const value = +input.value;

  const size = (value - min) / (max - min) * 100;

  return size;
}
input[type='range'] {
  width: 400px;
}

input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
}

input[type='range']::-webkit-slider-runnable-track {
  height: 3px;
  background: linear-gradient(to right, #293043, #293043), #D7D7D7;
  background-size: var(--background-size, 0%) 100%;
  background-repeat: no-repeat;
  border-radius: 5px;

}

input[type='range']::-webkit-slider-thumb {
  width: 15px;
  height: 15px;
  cursor: pointer;
  background: #293043;
  border: solid white 1px;
  border-radius: 50%;
  margin-top: -6px;
  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.4);
}

/** FF*/

input[type="range"]::-moz-range-progress {
  background-color: #293043;
  border-radius: 5px;
}

input[type="range"]::-moz-range-track {
  background-color: #D7D7D7;
  border-radius: 5px;
}

input[type="range"]::-moz-range-thumb {
  width: 15px;
  height: 15px;
  cursor: pointer;
  background: #293043;
  border: solid white 1px;
  border-radius: 50%;
  margin-top: -6px;
  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.4);
}
<input type="range" min="5" max="95" step="1" value="15">

This works on Chrome and Firefox :).

like image 92
Kurtil Avatar answered Oct 04 '22 03:10

Kurtil


Interesting approach being used by the Ionic framework for styling the range input track with just CSS. They are adding a ::before pseudo-element to the ::-webkit-slider-thumb, making it as wide as possible and then positioning it on top of the track. (I couldn't get border-radius to work with it.)

input[type='range'] {
  width: 210px;
  height: 30px;
  overflow: hidden;
  cursor: pointer;
}
input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
  width: 200px;
  height: 10px;
  background: #AAA;
}
input[type='range']::-webkit-slider-thumb {
  position: relative;
  height: 30px;
  width: 30px;
  margin-top: -10px;
  background: steelblue;
  border-radius: 50%;
  border: 2px solid white;
}
input[type='range']::-webkit-slider-thumb::before {
  position: absolute;
  content: '';
  height: 10px; /* equal to height of runnable track */
  width: 500px; /* make this bigger than the widest range input element */
  left: -502px; /* this should be -2px - width */
  top: 8px; /* don't change this */
  background: #777;
}
<div class="container">
  <input type="range" min="0" max="100" value="10" />
</div>

As far as I am aware there is no pure CSS way to do this for Webkit powered browsers (and FF). IE provides a way to style the two portions of the track using -ms-fill-lower and -ms-fill-upper but there are no equivalents in WebKit and hence JavaScript will be needed.

You could use a linear-gradient as background image for the runnable track and then change the background-size using JavaScript to achieve the required effect. As question is specific to Webkit, the snippet provided currently works only in Webkit powered browsers. This method does allow us to add a border-radius to the track.

This snippet was adapted from Ana Tudor's CodePen Demo. That demo has ways to make it work in other browsers also.

window.onload = function() {
  var input = document.querySelector('input[type=range]'),
    style_el = document.createElement('style'),
    styles = [],
    track_sel = ['::-webkit-slider-runnable-track'];
  document.body.appendChild(style_el);

  styles.push('');

  input.addEventListener('input', function() {
    var min = this.min || 0,
      max = this.max || 100,
      c_style, u, edge_w, val, str = '';

    this.setAttribute('value', this.value);

    val = this.value + '% 100%';
    str += 'input[type="range"]' + track_sel[0] + '{background-size:' + val + '}';

    styles[0] = str;
    style_el.textContent = styles.join('');
  }, false);
}
input[type='range'] {
  width: 210px;
  height: 50px;
  cursor: pointer;
}
input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
  width: 200px;
  height: 10px;
  background: linear-gradient(to right, #777, #777), #AAA;
  background-size: 10% 100%;
  background-repeat: no-repeat;
  border-radius: 5px;
}
input[type='range']::-webkit-slider-thumb {
  height: 30px;
  width: 30px;
  margin-top: -10px;
  background: steelblue;
  border-radius: 50%;
  border: 2px solid white;
}
<div class="container">
  <input type="range" min="0" max="100" value="10" />
</div>
like image 27
Harry Avatar answered Oct 04 '22 03:10

Harry