Skip to content
Advertisement

How to add custom styles to input type=”range”

I have 4 custom input[type=”range”] on my page. I used some JS and CSS to add styles, but it seems that only the first one works properly. What am I doing wrong and how to make all of them act like the first one? I don’t want it to be like a regular range and I thought that JS + CSS trick will be the best option. Nevertheless, if you know the way to make it work, I’ll be glad to try it.

Here’s the link to codepen: https://codepen.io/tomavl/pen/bGabZvj

var fillColor = "#9D3C3C",
  emptyColor = "#DDDDDD";

document
  .querySelector(".input-range--custom")
  .addEventListener("input", function () {
    var percent = (100 * (this.value - this.min)) / (this.max - this.min) + "%";
    //  this.setAttribute('value', this.value);
    //  this.setAttribute('title', this.value);
    this.style.backgroundImage = `linear-gradient( to right, ${fillColor}, ${fillColor} ${percent}, ${emptyColor} ${percent})`;
  });
input[type="range"].input-range--custom {
  -webkit-appearance: none;
  width: 100%;
  margin: 4px 0;
  background-image: linear-gradient(
      to right,
      rgb(157, 60, 60),
      rgb(157, 60, 60) 48%,
      rgb(221, 221, 221) 48%
    );
  border-radius: 20px 20px 0px 0px;
}

input[type="range"].input-range--custom:focus {
  outline: none;
}

input[type="range"].input-range--custom::-webkit-slider-runnable-track {
  width: 100%;
  height: 4px;
  cursor: pointer;
}

input[type="range"].input-range--custom:after {
  width: 20%;
  height: 4px;
  background-color: #9d3c3c;
}

input[type="range"].input-range--custom::-webkit-slider-thumb {
  height: 16px;
  width: 16px;
  border-radius: 15px;
  background: #ffffff;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: -5.5px;
  background: #9d3c3c;
  border: 2px solid #ffffff;
  box-sizing: border-box;
  box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.15);
}
<div class="range">
  <h5>Distance</h5>
  <div class="_flex-col range__container" style="width: 280px">
    <label for="distance"></label>
    <input id="distance" type="range" class="input-range--custom" min="0" max="50">
  </div>
</div>

<div class="range">
  <h5>Square</h5>
  <div class="_flex-col range__container" style="width: 280px">
    <label for="square"></label>
    <input id="square" type="range" class="input-range--custom" min="0" max="50">
  </div>
</div>

<div class="range">
  <h5>Min height</h5>
  <div class="_flex-col range__container" style="width: 280px">
    <label for="minheight"></label>
    <input id="minheight" type="range" class="input-range--custom" min="0" max="50">
  </div>

</div>

<div class="range">
  <h5>Max height</h5>
  <div class="_flex-col range__container" style="width: 280px">
    <label for="maxheight"></label>
    <input id="maxheight" type="range" class="input-range--custom" min="0" max="50">
  </div>
</div>

Advertisement

Answer

Using document.querySelector(".input-range--custom"), you are selecting only the first input with the class input-range--custom.

So, the rest of the inputs do not have an event listener.

In order to select all of them, you need to use querySelectorAll instead of querySelector.

Replace your JS code with following:

var fillColor = "#9D3C3C",
  emptyColor = "#DDDDDD";

const rangeInputs = document.querySelectorAll(".input-range--custom")

rangeInputs.forEach(input => {
    input.addEventListener("input", function () {
      var percent = (100 * (this.value - this.min)) / (this.max - this.min) + "%";
      //  this.setAttribute('value', this.value);
      //  this.setAttribute('title', this.value);
      this.style.backgroundImage = `linear-gradient( to right, ${fillColor}, 
      ${fillColor} ${percent}, ${emptyColor} ${percent})`;
  });
})
Advertisement