Градиентная рамка для ползунка input type range

Рейтинг: 1Ответов: 1Опубликовано: 14.06.2023

Есть input type range. У него нужно сделать градиентный фон для дорожки (это я сделал) и кружок, с градиентной рамкой, но вот беда, не нашел способа, как сделать ползунок в виде кружка с градиентной рамкой. Можно ли сделать это без js или хотя бы не имитируя работу ползунка при помощи js?

input[type=range] {
    height: 24px;
    -webkit-appearance: none;
    margin: 10px 0;
    width: 1052px;
    margin-top: 167px;
    position: relative;
}
input[type=range]:focus {
    outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
    width: 100%;
    height: 24px;
    cursor: pointer;
    background: linear-gradient(90deg, rgba(16,27,105,1) 0%, rgba(169,0,67,1) 100%);
    border-radius: 20px;
    border: 0px solid #ffffff;
    z-index: 1;
}
input[type=range]::-webkit-slider-thumb {
    border: 10px solid rgba(166,103,255,1);
    height: 133px;
    width: 133px;
    border-radius: 50%;
    background: #fff;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -50px;
}

input[type=range]::-moz-range-track {
    width: 100%;
    height: 24px;
    cursor: pointer;
    background: linear-gradient(90deg, rgba(16,27,105,1) 0%, rgba(169,0,67,1) 100%);
    border-radius: 20px;
    border: 0px solid #ffffff;
    z-index: 1;
}
input[type=range]::-moz-range-thumb {
    border: 10px solid rgba(166,103,255,1);
    height: 133px;
    width: 133px;
    border-radius: 50%;
    background: #fff;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -50px;
}
input[type=range]::-ms-track {
    width: 100%;
    height: 24px;
    cursor: pointer;
    background: transparent;
    border-color: transparent;
    color: transparent;
}
input[type=range]::-ms-fill-lower {
    background: linear-gradient(90deg, rgba(16,27,105,1) 0%, rgba(169,0,67,1) 100%);
    border-radius: 20px;
}
input[type=range]::-ms-fill-upper {
    background: linear-gradient(90deg, rgba(16,27,105,1) 0%, rgba(169,0,67,1) 100%);
    border-radius: 20px;
}
input[type=range]::-ms-thumb {
    border: 10px solid rgba(166,103,255,1);
    height: 133px;
    width: 133px;
    border-radius: 50%;
    background: #fff;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -50px;
}
<input class="gradient" type="range" min="500" max="800000" value="250000" name="range" step="1">

Ответы

▲ 4Принят

Можно ли сделать это без js или хотя бы не имитируя работу ползунка при помощи js?

Совсем без JS не получится. Но, без имитации и сложных скриптов, вполне возможно.

Для этого назначаем кнопке ползунка множественный фон и задаём необходимый градиент. Также, для удобства изменения значений в нескольких местах сразу, используем CSS-переменные (к тому же они используются в некоторых вычислениях).

Главный (и наверное единственный) минус - невозможность указать ширину в процентах.

const GRADIENT_RANGE = document.querySelector('.gradient');
GRADIENT_RANGE.addEventListener('input', function(ev) {
  let percent = (100 * (+this.value - +this.min)) / (+this.max - +this.min);
  this.style.setProperty('--percent', percent);
});
GRADIENT_RANGE.dispatchEvent(new Event('input'));
input[type="range"] {
  --width: 90vw;
  /* --gradient: linear-gradient(90deg, #101b69 50%, #a90043 50%); оригинальный */
  --gradient: linear-gradient(90deg, red, orange, yellow, lime, cyan, blue, purple);
  --thumb-sz: 133px;
  --thumb-br: 10px;
  --thumb-bg: 
    50% 50% / 100% 100% radial-gradient(circle calc(var(--thumb-sz) / 2 - var(--thumb-br)), #fff 0 98%, #fff0 100%) no-repeat, 
    calc(var(--percent) * 1%) 0 / var(--width) 100% var(--gradient) no-repeat;
  --track-h: 24px;
  -webkit-appearance: none;
  margin: calc(var(--thumb-sz) / 2) auto;
  display: block;
  width: var(--width);
}
input[type="range"]:focus { outline: none; }

input[type="range"]::-webkit-slider-runnable-track {
  height: var(--track-h);
  width: 100%;
  border-radius: 1000px;
  background: var(--gradient);
  cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  position: relative;
  top: 50%;
  height: var(--thumb-sz);
  width: var(--thumb-sz);
  border-radius: 50%;
  transform: translateY(-50%);
  background: var(--thumb-bg);
  cursor: pointer;
}

input[type="range"]::-moz-range-track {
  height: var(--track-h);
  width: 100%;
  border: none;
  border-radius: 1000px;
  background: var(--gradient);
  cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
  -webkit-appearance: none;
  height: var(--thumb-sz);
  width: var(--thumb-sz);
  border: none;
  border-radius: 50%;
  background: var(--thumb-bg);
  cursor: pointer;
}

input[type="range"]::-ms-track {
  height: var(--track-h);
  width: 100%;
  cursor: pointer;
  border-color: transparent;
  color: transparent;
  background: transparent;
}
input[type="range"]::-ms-fill-lower {
  border-radius: 1000px;
  background: var(--gradient);
}
input[type="range"]::-ms-fill-upper {
  border-radius: 1000px;
  background: var(--gradient);
}
input[type="range"]::-ms-thumb {
  -webkit-appearance: none;
  position: relative;
  top: 50%;
  height: var(--thumb-sz);
  width: var(--thumb-sz);
  border: none;
  border-radius: 50%;
  transform: translateY(-50%);
  background: var(--thumb-bg);
  cursor: pointer;
}
<input class="gradient" type="range" min="500" max="800000" value="250000" name="range" step="1">

Извините, но префиксы -ms- негде было протестировать :-)

в моем случае градиент у полоски и у ползунка должен быть различным. В добавок, градиент у ползунка не должен меняться при перемещении.

Тогда задача упрощается - убираем JS и добавляем треку и кнопке разные градиенты. В таком варианте, работает даже процентная ширина ползунка.

input[type="range"] {
  --track-gradient: linear-gradient(90deg, #101b69 0%, #a90043 100%);
  --thumb-gradient: conic-gradient(red, orange, yellow, lime, cyan, blue, purple, red);
  --thumb-sz: 133px;
  --thumb-br: 10px;
  --thumb-bg: 
    50% 50% / 100% 100% radial-gradient(circle calc(var(--thumb-sz) / 2 - var(--thumb-br)), #fff 0 98%, #fff0 100%) no-repeat, 
    50% 50% / 100% 100% var(--thumb-gradient) no-repeat;
  --track-h: 24px;
  -webkit-appearance: none;
  margin: calc(var(--thumb-sz) / 2) auto;
  display: block;
  width: 100%;
}
input[type="range"]:focus { outline: none; }

input[type="range"]::-webkit-slider-runnable-track {
  height: var(--track-h);
  width: 100%;
  border-radius: 1000px;
  background: var(--track-gradient);
  cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  position: relative;
  top: 50%;
  height: var(--thumb-sz);
  width: var(--thumb-sz);
  border-radius: 50%;
  transform: translateY(-50%);
  background: var(--thumb-bg);
  cursor: pointer;
}

input[type="range"]::-moz-range-track {
  height: var(--track-h);
  width: 100%;
  border: none;
  border-radius: 1000px;
  background: var(--track-gradient);
  cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
  -webkit-appearance: none;
  height: var(--thumb-sz);
  width: var(--thumb-sz);
  border: none;
  border-radius: 50%;
  background: var(--thumb-bg);
  cursor: pointer;
}

input[type="range"]::-ms-track {
  height: var(--track-h);
  width: 100%;
  cursor: pointer;
  border-color: transparent;
  color: transparent;
  background: transparent;
}
input[type="range"]::-ms-fill-lower {
  border-radius: 1000px;
  background: var(--track-gradient);
}
input[type="range"]::-ms-fill-upper {
  border-radius: 1000px;
  background: var(--track-gradient);
}
input[type="range"]::-ms-thumb {
  -webkit-appearance: none;
  position: relative;
  top: 50%;
  height: var(--thumb-sz);
  width: var(--thumb-sz);
  border: none;
  border-radius: 50%;
  transform: translateY(-50%);
  background: var(--thumb-bg);
  cursor: pointer;
}
<input class="gradient" type="range" min="500" max="800000" value="250000" name="range" step="1">