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

实现无占位自定义滚动条:匹配默认行为及滚动进度显示

自定义无占位滚动条实现方案

需求说明

需要实现一款与默认滚动条行为完全一致的自定义滚动条,核心要求是完全不占用页面空间,计划通过z-index和position:absolute实现,但不确定如何正确同步滚动进度。开发环境为桌面应用,不支持overflow:overlay属性,也无法使用第三方自定义滚动条库。

实现思路

  • 彻底隐藏原生滚动条:通过CSS各浏览器兼容写法隐藏原生滚动条,避免其占用布局空间
  • 动态计算滑块高度:根据容器可视高度与内容总高度的比例,计算出自定义滚动条滑块的高度,公式为:(容器可视高度 / 内容总高度) * 容器可视高度
  • 实时同步滚动位置:监听容器滚动事件,计算滚动百分比,同步更新自定义滑块的top偏移量
  • 支持滑块拖拽交互:添加鼠标拖拽滑块的逻辑,模拟原生滚动条的拖拽滚动行为
  • 边界处理:当内容高度不足容器可视高度时,自动隐藏自定义滚动条

完整实现代码

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Custom Scrollbar</title>
</head>
<body>
  <div class="scroll">
    <div class="scrollbar-track">
      <div class="scrollbar-thumb"></div>
    </div>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>aaaaa</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
    <a>bbbbb</a>
  </div>
</body>
</html>

CSS

.scroll {
  display: flex;
  flex-direction: column;
  height: 200px;
  width: 200px;
  overflow-y: auto;
  position: relative;
  padding-right: 0;
}

/* 滚动条轨道 */
.scrollbar-track {
  position: absolute;
  right: 2px;
  top: 2px;
  bottom: 2px;
  width: 6px;
  border-radius: 3px;
  background: rgba(0,0,0,0.1);
  opacity: 0;
  transition: opacity 0.2s;
  z-index: 1;
}

/* 滚动条滑块 */
.scrollbar-thumb {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  border-radius: 3px;
  background: rgba(0,0,0,0.5);
  cursor: pointer;
}

/* 鼠标悬停时显示滚动条 */
.scroll:hover .scrollbar-track {
  opacity: 1;
}

/* 隐藏原生滚动条 */
.scroll::-webkit-scrollbar {
  display: none;
}
.scroll {
  scrollbar-width: none;
}
.scroll::-ms-scrollbar {
  display: none;
}

JavaScript

document.addEventListener('DOMContentLoaded', function() {
  const scrollContainer = document.querySelector('.scroll');
  const scrollTrack = document.querySelector('.scrollbar-track');
  const scrollThumb = document.querySelector('.scrollbar-thumb');
  
  // 初始化滚动条状态
  updateScrollbar();

  // 监听容器滚动事件
  scrollContainer.addEventListener('scroll', updateScrollbar);

  // 监听窗口大小变化,重新计算滚动条
  window.addEventListener('resize', updateScrollbar);

  // 滑块拖拽逻辑
  let isDragging = false;
  let startY = 0;
  let startScrollTop = 0;

  scrollThumb.addEventListener('mousedown', function(e) {
    isDragging = true;
    startY = e.clientY;
    startScrollTop = scrollContainer.scrollTop;
    e.preventDefault();
  });

  document.addEventListener('mousemove', function(e) {
    if (!isDragging) return;
    const deltaY = e.clientY - startY;
    const trackHeight = scrollTrack.clientHeight;
    const thumbHeight = scrollThumb.clientHeight;
    const scrollRatio = deltaY / (trackHeight - thumbHeight);
    const totalScroll = scrollContainer.scrollHeight - scrollContainer.clientHeight;
    scrollContainer.scrollTop = startScrollTop + scrollRatio * totalScroll;
  });

  document.addEventListener('mouseup', function() {
    isDragging = false;
  });

  // 更新滚动条位置和尺寸
  function updateScrollbar() {
    const containerHeight = scrollContainer.clientHeight;
    const contentHeight = scrollContainer.scrollHeight;
    const scrollTop = scrollContainer.scrollTop;

    // 内容不足一屏时隐藏滚动条
    if (contentHeight <= containerHeight) {
      scrollTrack.style.display = 'none';
      return;
    }
    scrollTrack.style.display = 'block';

    // 计算滑块高度
    const thumbHeight = Math.max(20, (containerHeight / contentHeight) * containerHeight);
    scrollThumb.style.height = `${thumbHeight}px`;

    // 计算滑块位置
    const scrollPercentage = (scrollTop / (contentHeight - containerHeight)) * 100;
    const maxTop = scrollTrack.clientHeight - thumbHeight;
    const top = (scrollPercentage / 100) * maxTop;
    scrollThumb.style.top = `${top}px`;
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:06:02