You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Range Slider Tooltip悬停Thumb时消失及居中问题求助

解决方案:Range Slider Tooltip 始终显示并居中于滑块顶部

问题分析

  1. Tooltip悬停消失:代码中给滑块thumb绑定了mouseout事件,当鼠标从thumb移到Tooltip上时会触发该事件,导致Tooltip被隐藏;同时你需要Tooltip始终可见,这些事件监听完全多余。
  2. Tooltip无法居中:当前代码仅将Tooltip的左边缘对齐thumb的左边缘,未考虑Tooltip自身宽度,导致无法居中。

修改步骤

1. 移除多余的鼠标事件监听

删除以下代码块:

thumbLeft.addEventListener("mouseover", function() {
  tooltipLeft.style.display = "block";
});

thumbLeft.addEventListener("mouseout", function() {
  tooltipLeft.style.display = "none";
});

thumbRight.addEventListener("mouseover", function() {
  tooltipRight.style.display = "block";
});

thumbRight.addEventListener("mouseout", function() {
  tooltipRight.style.display = "none";
});

2. 调整Tooltip的CSS样式

更新.tooltip的CSS,添加水平居中的变换:

.tooltip {
  position: absolute;
  display: none;
  background-color: #1C64F2;
  color: #FFFFFF;
  padding: var(--05, 2px) var(--2, 8px);
  border-radius: 5px;
  font-size: 12px;
  white-space: nowrap;
  opacity: 1;
  transform: translateX(-50%); /* 添加这行实现水平居中 */
}

3. 修正Tooltip位置计算逻辑

更新updateTooltipPosition函数,让Tooltip精准居中于thumb顶部:

function updateTooltipPosition() {
  var thumbLeftPosition = thumbLeft.getBoundingClientRect();
  var thumbRightPosition = thumbRight.getBoundingClientRect();
  // 获取父容器的偏移量,避免滚动时位置偏移
  var containerOffset = document.querySelector('.middle').getBoundingClientRect();

  tooltipLeft.style.display = "block";
  // 左Tooltip:left设置为thumb中心,top设置为thumb顶部上方
  tooltipLeft.style.left = (thumbLeftPosition.left - containerOffset.left + thumbLeftPosition.width / 2) + "px";
  tooltipLeft.style.top = (thumbLeftPosition.top - containerOffset.top - tooltipLeft.offsetHeight - 5) + "px";
  tooltipLeft.innerHTML = PriceMinSlider.value;

  tooltipRight.style.display = "block";
  // 右Tooltip:同样设置为thumb中心和顶部上方
  tooltipRight.style.left = (thumbRightPosition.left - containerOffset.left + thumbRightPosition.width / 2) + "px";
  tooltipRight.style.top = (thumbRightPosition.top - containerOffset.top - tooltipRight.offsetHeight - 5) + "px";
  tooltipRight.innerHTML = PriceMaxSlider.value;
}

注:添加容器偏移量计算是为了避免页面滚动时Tooltip位置出现偏差,因为getBoundingClientRect()返回的是相对于视口的位置,减去容器的视口偏移后得到相对于父容器的位置,更准确。

完整修改后的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
    .middle {
  position: relative;
  width: 100%;
  max-width: 500px;
}

.slider {
  position: relative;
  z-index: 1;
  height: var(--2, 8px);
}

.slider>.track {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  border-radius: 5px;
  background-color: #E5E7EB;
}

.slider>.range {
  position: absolute;
  z-index: 2;
  left: 25%;
  right: 25%;
  top: 0;
  bottom: 0;
  border-radius: 5px;
  background-color: #1C64F2;
}

.slider>.thumb {
  position: absolute;
  z-index: 3;
  width: 22px;
  height: 22px;
  background-color: #FFFFFF;
  border-radius: 50%;
  box-shadow: 0 0 0 0 rgba(98, 0, 238, .1);
  transition: box-shadow .3s ease-in-out;
  stroke-width: 1px;
  stroke: var(--gray-200, #E5E7EB);
  filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.08));
}

.slider>.thumb.left {
  left: 25%;
  transform: translate(-15px, -10px);
}

.slider>.thumb.right {
  right: 25%;
  transform: translate(15px, -10px);
}

input[type=range] {
  position: absolute;
  pointer-events: none;
  -webkit-appearance: none;
  z-index: 2;
  height: 10px;
  width: 100%;
  opacity: 0;
}

input[type=range]::-webkit-slider-thumb {
  pointer-events: all;
  width: 22px;
  height: 22px;
  border-radius: 0;
  border: 0 none;
  background-color: red;
  -webkit-appearance: none;
}

.tooltip {
  position: absolute;
  display: none;
  background-color: #1C64F2;
  color: #FFFFFF;
  padding: var(--05, 2px) var(--2, 8px);
  border-radius: 5px;
  font-size: 12px;
  white-space: nowrap;
  opacity: 1;
  transform: translateX(-50%); /* 添加水平居中变换 */
}
</style>
</head>
<body>

    <div class="price-range-section mt-5">
        <label for="Price Range">Price Range</label>
        <div class="middle">
          <div class="multi-range-slider">
            <input type="range" id="price-min-slider" min="0" max="100" value="25">
            <input type="range" id="price-max-slider" min="0" max="100" value="75">
      
            <div class="slider">
              <div class="track"></div>
              <div class="range"></div>
              <div class="thumb left"></div>
              <div class="thumb right"></div>
            </div>
      
            <!-- Tooltips -->
            <div class="tooltip" id="tooltip-left"></div>
            <div class="tooltip" id="tooltip-right"></div>
          </div>
        </div>
      </div>
    

      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
      <script>
        var PriceMinSlider = document.getElementById("price-min-slider");
var PriceMaxSlider = document.getElementById("price-max-slider");

var thumbLeft = document.querySelector(".slider > .thumb.left");
var thumbRight = document.querySelector(".slider > .thumb.right");
var range = document.querySelector(".slider > .range");

var tooltipLeft = document.getElementById("tooltip-left");
var tooltipRight = document.getElementById("tooltip-right");

function setLeftValue() {
  var _this = PriceMinSlider,
    min = parseInt(_this.min),
    max = parseInt(_this.max);

  _this.value = Math.min(parseInt(_this.value), parseInt(PriceMaxSlider.value) - 1);

  var percent = ((_this.value - min) / (max - min)) * 100;

  thumbLeft.style.left = percent + "%";
  range.style.left = percent + "%";
  updateTooltipPosition();
}

setLeftValue();

function setRightValue() {
  var _this = PriceMaxSlider,
    min = parseInt(_this.min),
    max = parseInt(_this.max);

  _this.value = Math.max(parseInt(_this.value), parseInt(PriceMinSlider.value) + 1);

  var percent = ((_this.value - min) / (max - min)) * 100;

  thumbRight.style.right = (100 - percent) + "%";
  range.style.right = (100 - percent) + "%";
  updateTooltipPosition();
}

setRightValue();

function updateTooltipPosition() {
  var thumbLeftPosition = thumbLeft.getBoundingClientRect();
  var thumbRightPosition = thumbRight.getBoundingClientRect();
  // 获取父容器的视口偏移量
  var containerOffset = document.querySelector('.middle').getBoundingClientRect();

  tooltipLeft.style.display = "block";
  // 计算相对于父容器的left和top,确保居中且在顶部
  tooltipLeft.style.left = (thumbLeftPosition.left - containerOffset.left + thumbLeftPosition.width / 2) + "px";
  tooltipLeft.style.top = (thumbLeftPosition.top - containerOffset.top - tooltipLeft.offsetHeight - 5) + "px";
  tooltipLeft.innerHTML = PriceMinSlider.value;

  tooltipRight.style.display = "block";
  tooltipRight.style.left = (thumbRightPosition.left - containerOffset.left + thumbRightPosition.width / 2) + "px";
  tooltipRight.style.top = (thumbRightPosition.top - containerOffset.top - tooltipRight.offsetHeight - 5) + "px";
  tooltipRight.innerHTML = PriceMaxSlider.value;
}

PriceMinSlider.addEventListener("input", setLeftValue);
PriceMaxSlider.addEventListener("input", setRightValue);

PriceMinSlider.addEventListener("mousedown", function() {
  thumbLeft.classList.add("active");
});

PriceMinSlider.addEventListener("mouseup", function() {
  thumbLeft.classList.remove("active");
});

PriceMaxSlider.addEventListener("mousedown", function() {
  thumbRight.classList.add("active");
});

PriceMaxSlider.addEventListener("mouseup", function() {
  thumbRight.classList.remove("active");
});

      </script>
</body>
</html>

内容的提问来源于stack exchange,提问作者Rejuan hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 12:05:55