javascripthtmlcssinput-type-range

trouble with functionality of custom styled input type range


If you drag the thumb it won't work because apparently it is not a part of input when I inspect it with devtools, new elements don't consider it's position and cover it

if you remove the paragraph after the input you can drag the thumb and the gradient will change according to it's position.

is there a way to keep the thumb working even when I add elements after the input?

if you change #slider padding the gradient will weirdly grow, if you add margin the thumb won't work again.

document.querySelector('input').addEventListener('input', ({target: t}) => t.style.backgroundSize = (t.value/t.max) * 100 + '%');
body {
  display: flex;
  align-items: center;
  flex-direction: column;
  padding: 0 10%;
  font-family: sans-serif;
}

* {
  font-weight: 200;
}

.tags {
  display: flex;
  margin: 25px 0;
}

span {
  flex: 1 1;
  padding-right: 30px;
  align-self: flex-end;
  font-size: 14px;
}

span:last-child {
  text-align: right;
  padding-right: 0px;
}

input {
  position: relative;
  width: 100%;
  cursor: pointer;
  outline: none;
  /* TRACK */
  -webkit-appearance: none;
  /* Hides the slider so that custom slider can be made */
  background: linear-gradient(to left, #8074AE, #CBB0DF) no-repeat;
  background-size: 50%;
}
input::-webkit-slider-runnable-track {
  height: 14px;
  background: #E7E8E9;
  z-index: -1;
}
input::-moz-range-track {
  height: 14px;
  background: #E7E8E9;
  z-index: -1;
}
input::after {
  content: '';
  position: absolute;
  display: block;
  width: 100%;
  height: 10px;
  background: linear-gradient(to left top, transparent 50%, white 55%);
  user-select: none;
  pointer-events: none;
}
input::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  margin-top: 28px;
  /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
  border: solid 2px #E7E8E9;
  border-radius: 0px 50% 50%;
  transform: rotate(45deg);
}
input::-moz-range-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin-top: 15px;
  /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
  border-radius: 8px;
}
<h1>Уровень владения JavaScript</h1>
<div class="tags">
  <span>Не владею</span>
  <span>Использую готовые решения</span>
  <span>Использую готовые решения и умею переделывать</span>
  <span>Пишу сложный JS с нуля</span>
</div>
<input type="range" min="0" max="1000">
<p>Help me</p>


Solution

  • Wrap the input in a containing element and set the height on that element in order to push the sibling element down below the range-thumb Set the z-index of the containing element as well so that it is above the sibling element.:

    document.querySelector('input').addEventListener('input', ({target: t}) => t.style.backgroundSize = (t.value/t.max) * 100 + '%');
    body {
      display: flex;
      align-items: center;
      flex-direction: column;
      padding: 0 10%;
      font-family: sans-serif;
    }
    
    * {
      font-weight: 200;
    }
    
    .tags {
      display: flex;
      margin: 25px 0;
    }
    
    span {
      flex: 1 1;
      padding-right: 30px;
      align-self: flex-end;
      font-size: 14px;
    }
    
    span:last-child {
      text-align: right;
      padding-right: 0px;
    }
    .input-container {
      display: block;
      width: 100%;
      height: 55px;
      z-index:10;
    }
    input {
      position: relative;
      width: 100%;
      cursor: pointer;
      outline: none;
      /* TRACK */
      -webkit-appearance: none;
      /* Hides the slider so that custom slider can be made */
      background: linear-gradient(to left, #8074AE, #CBB0DF) no-repeat;
      background-size: 50%;
    }
    input::-webkit-slider-runnable-track {
      height: 14px;
      background: #E7E8E9;
      z-index: -1;
    }
    input::-moz-range-track {
      height: 14px;
      background: #E7E8E9;
      z-index: -1;
    }
    input::after {
      content: '';
      position: absolute;
      display: block;
      width: 100%;
      height: 10px;
      background: linear-gradient(to left top, transparent 50%, white 55%);
      user-select: none;
      pointer-events: none;
    }
    input::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 22px;
      height: 22px;
      margin-top: 28px;
      /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
      border: solid 2px #E7E8E9;
      border-radius: 0px 50% 50%;
      transform: rotate(45deg);
    }
    input::-moz-range-thumb {
      -webkit-appearance: none;
      width: 20px;
      height: 20px;
      margin-top: 15px;
      /* You need to specify a margin in Chrome, but in Firefox and IE it is automatic */
      border-radius: 8px;
    }
    <h1>Уровень владения JavaScript</h1>
    <div class="tags">
      <span>Не владею</span>
      <span>Использую готовые решения</span>
      <span>Использую готовые решения и умею переделывать</span>
      <span>Пишу сложный JS с нуля</span>
    </div>
    <div class="input-container">
      <input type="range" min="0" max="1000">
    </div>
    <p>Help me</p>