【问题标题】:CSS: How to style HTML5 input range to have different background colour and width before thumb?CSS:如何设置 HTML5 输入范围的样式以在拇指之前具有不同的背景颜色和宽度?
【发布时间】:2020-11-03 23:04:47
【问题描述】:

我正在使用 HTML5 输入范围,我需要设置滑块的样式,使其具有不同的颜色 (black) 和宽度(2px) 直到滑块的位置,并将其设置为#3938371px 在滑块之后。
为了说明下图,它之前更暗更厚,之后更薄:

到目前为止,我所取得的成就是,在整个滑块中都有#393837 的颜色。

.slider {
  width: 100%;
  height: 1px;
  outline: none;
  background: #393837;
  -webkit-appearance: none;
}

.slider::-webkit-slider-thumb {
  width: 8px;
  height: 8px;
  cursor: pointer;
  appearance: none;
  background: black;
  border-radius: 50%;
  -webkit-appearance: none;
}

.slider::-moz-range-thumb {
  width: 8px;
  height: 8px;
  border: none;
  cursor: pointer;
  border-radius: 50%;
  background: black;
}
<input min="1" max="100" type="range" className="slider" />

附:我正在使用 reactJS,所以我不想使用 jQuery

注意:我的问题已被标记为重复,但other question 中的解决方案对输入元素使用硬编码宽度,而我没有。

【问题讨论】:

标签: javascript html css reactjs input


【解决方案1】:

通过使用“幻觉”元素来伪装成滑块的一部分,您可以实现您想要的效果。

我对 ReactJS 还不是很熟悉,所以我用 vanilla javascript 编写了它,但它应该很容易转换为 react 代码。

通过监听滑块上的更改和输入事件,您可以更新“幻觉”以变小或变大。
通过监听幻象的点击,可以让滑块有较大的值,然后触发change事件更新幻象的宽度。

请注意,我在代码中使用了作用域引用。根据您的代码库,您可能希望在每次触发事件时创建这些类属性或重新获取它们。

希望这能给你足够的灵感来提出反应解决方案。

/**
 * getting all the sliders in the document.
 * define how big the thumb is here.
 */
const SLIDER_THUMB_SIZE = 8;
Array.from(document.querySelectorAll('.slider'))
      .forEach(function(element) {
         /** a reference to our illusion of a slider **/
         let illusion = element.parentNode.querySelector('.slider-illusion');
         /** We need this to save our state without having to look it up on the element **/
         let currentWidth;
         
         /** Our change handler, to update the width of our thin slider piece **/
         let changeWidth = (e) => {
             
             /** get the current actual width of our input element **/
             let width = parseInt(window.getComputedStyle(element).getPropertyValue("width"));
             /** Calculate the left offset **/
             let left = ((element.value - element.min) / (element.max - element.min)) * ((width - SLIDER_THUMB_SIZE)) + SLIDER_THUMB_SIZE * 1.25 ;
             /** set the proper width **/
             illusion.style.width = (width - left + SLIDER_THUMB_SIZE) + "px";
             /** update out position **/
             illusion.style.left = left+"px" ;  
         };
         
         /** When a click is registered on the illusion, we need to update our
             value in the slider. **/
         let illusionTrigger = (e) => {
             /** Where was clicked in the illusion? **/
             let offset = e.offsetX;
             /** how wide are the parts in our illusion for each change **/
             let part = illusion.clientWidth / (element.max - element.value) ;
             /** calculate the value that needs to be added to the current slider value **/
             let change = Math.round(offset / part);
             /** force a change if there is a click behind the thumb **/
             if(change == 0) {
                 change = 1;
             }
             /** update the slider **/
             element.value = parseInt(element.value) + change;
             /** Trigger a change notification and a redraw of the illusion **/
             element.dispatchEvent(new Event('change'));
         };
         /** trigger it once to update everything to the correct position **/
         changeWidth();
         /** bind the event handler to the input and change event to enable dragging of the thumb**/
         element.addEventListener('input', changeWidth);
         element.addEventListener('change', changeWidth);
         let forFun = (e) => {
              document.getElementById(element.name).innerText = element.value;
         };
         element.addEventListener('input', forFun);
         element.addEventListener('change', forFun);
         /** listen to the click event on the illusion **/
         illusion.addEventListener('click', illusionTrigger);
});
.slider-container {
    position:relative;
    height: 10px;
    width: 100%;
    overflow: hidden;
}
.slider-illusion {
   position: absolute;
   top:0px;
   background: white;;
   width: 50%;
   left: calc(50% + 2px);
   height:10px;
   cursor: pointer;
}
.slider-illusion .line {
  position: absolute;
  top: 3px;
  height: 2px;
  background-color: black;
  width: 100%;

}
.slider {
  /**
   * absolute positioning to assure both elements align the same
   */
  position:absolute;
  top:0px;
  left:0px;
  
  width: 100%;
  height: 5px;
  outline: none;
  background: #393837;
  -webkit-appearance: none;
}

.slider::-webkit-slider-thumb {
  width: 8px;
  height: 8px;
  cursor: pointer;
  appearance: none;
  background: black;
  border-radius: 50%;
  -webkit-appearance: none;
}

.slider::-moz-range-thumb {
  width: 8px;
  height: 8px;
  border: none;
  cursor: pointer;
  border-radius: 50%;
  background: black;
}
Select how many cups you want: <span id="cups">3</span>/5
<div class="slider-container">
  <input min="1" max="5" value="3" type="range" class="slider" name="cups" />
  <div class="slider-illusion" data-width="50%">
    <div class="line"></div>
  </div>
</div>
<br>
Select how many balls you want: <span id="balls">125</span>/500
<div class="slider-container">
  <input min="1" max="500" value="125" type="range"  class="slider" name="balls" />
  <div class="slider-illusion" data-width="50%">
    <div class="line"></div>
  </div>
</div>
<br>
select how many rounds to play: <span id="rounds">3</span>/10
<div class="slider-container">
  <input min="1" max="10" value="3" type="range" class="slider" name="rounds"/>
  <div class="slider-illusion" data-width="50%">
    <div class="line"></div>
  </div>
</div>

【讨论】:

  • 感谢您分享您的解决方案,但是当我开始向左滑动时,滑块拇指正在从右侧切割:)
  • @VinaySharma 我更新了我的代码,我正在修改它,因为它在 1 - 100 以外的任何其他值上都失败了。它现在如何工作?
  • 现在完美运行!拇指右侧的边缘略微可见,我会尝试弄清楚:)
  • @VinaySharma 是的,这与溢出等有关......并且还可以根据您网站中存在的其他 css 规则进行更改。我只是给出了如何使它工作的功能代码。此外,我刚刚在您回复后修复了当单击“next tot”拇指时它会跳到最后。
  • 好的,非常感谢您的解决方案。我会彻底通关的。很快也会发布我的解决方案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多