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

如何用CSS/JS实现类似Spotify网页的叠加式滚动条

实现叠加在内容上方的透明轨道自定义滚动条

纯CSS方案(WebKit内核浏览器适用)

由于overflow: overlay已被废弃,我们可以通过自定义WebKit滚动条样式,让滚动条直接叠加在容器内容上方,无需挤压内容空间。核心是调整滚动条布局逻辑,使其不占据容器宽度,同时设置轨道为透明。

修改后代码如下:

html,
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* 自定义WebKit滚动条 */
::-webkit-scrollbar {
  width: 25px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  width: 5px;
  background: #f2f2f28f;
  border-radius: 10px;
  border: 10px solid transparent;
  background-clip: content-box;
}

/* 居中容器 */
.house {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

/* 滚动容器 */
.parent {
  width: 450px;
  height: 450px;
  padding: 15px;
  background-image: linear-gradient(to top, #ff00ff, #16dc7c);
  border-radius: 10px;
  overflow-y: auto;
}

/* 子元素:宽度占满容器,让滚动条叠加在上方 */
.child {
  width: 100%;
  height: 200px;
  color: #ffffff;
  padding: 10px 65px 0px 60px;
  margin-bottom: 10px;
}

.child.ch1 {
  background-color: #264cb3;
}

.child.ch2 {
  background-color: #8728a7;
}

.child.ch3 {
  background-color: #ad9521;
}
<div class="house">
  <div class="parent">
    <div class="child ch1">
      滚动条应叠加在此div上方
    </div>
    <div class="child ch2">
      滚动条应叠加在此div上方
    </div>
    <div class="child ch3">
      滚动条应叠加在此div上方
    </div>
  </div>
</div>

关键说明:

  • 通过background-clip: content-box和透明边框,让滚动条滑块仅显示中间有效部分,视觉上贴合右侧且不挤压内容。
  • 子元素设置width:100%,完全填充容器宽度,滚动条直接叠加在上方。
  • 仅支持WebKit内核浏览器(Chrome、Edge、Safari等),火狐或IE需额外处理。

JavaScript方案(跨浏览器兼容,模拟Spotify式滚动条)

如果需要兼容所有浏览器,或实现更复杂的滚动交互,可以像Spotify一样用JS自定义滚动条。核心思路是隐藏原生滚动条,创建自定义滚动条元素,通过监听滚动事件同步位置。

实现代码:

html,
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.house {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

.parent {
  width: 450px;
  height: 450px;
  padding: 15px;
  background-image: linear-gradient(to top, #ff00ff, #16dc7c);
  border-radius: 10px;
  overflow-y: scroll;
  scrollbar-width: none;
  -ms-overflow-style: none;
  position: relative;
}

/* 隐藏WebKit原生滚动条 */
.parent::-webkit-scrollbar {
  display: none;
}

.child {
  width: 100%;
  height: 200px;
  color: #ffffff;
  padding: 10px 65px 0px 60px;
  margin-bottom: 10px;
}

.child.ch1 {
  background-color: #264cb3;
}

.child.ch2 {
  background-color: #8728a7;
}

.child.ch3 {
  background-color: #ad9521;
}

/* 自定义滚动条容器 */
.custom-scrollbar {
  position: absolute;
  top: 15px;
  right: 15px;
  width: 5px;
  height: calc(100% - 30px);
  border-radius: 10px;
  background: transparent;
}

/* 自定义滚动条滑块 */
.custom-scrollbar-thumb {
  position: absolute;
  width: 100%;
  background: #f2f2f28f;
  border-radius: 10px;
  cursor: pointer;
}
<div class="house">
  <div class="parent" id="scrollContainer">
    <div class="child ch1">
      滚动条应叠加在此div上方
    </div>
    <div class="child ch2">
      滚动条应叠加在此div上方
    </div>
    <div class="child ch3">
      滚动条应叠加在此div上方
    </div>
    <!-- 自定义滚动条 -->
    <div class="custom-scrollbar">
      <div class="custom-scrollbar-thumb" id="scrollThumb"></div>
    </div>
  </div>
</div>
const scrollContainer = document.getElementById('scrollContainer');
const scrollThumb = document.getElementById('scrollThumb');
const scrollbar = scrollThumb.parentElement;

// 更新滚动条位置和高度
function updateScrollbar() {
  const containerHeight = scrollContainer.clientHeight;
  const contentHeight = scrollContainer.scrollHeight;
  const thumbHeight = (containerHeight / contentHeight) * containerHeight;
  scrollThumb.style.height = `${Math.max(thumbHeight, 20)}px`;

  const scrollTop = scrollContainer.scrollTop;
  const scrollRatio = scrollTop / (contentHeight - containerHeight);
  const thumbTop = scrollRatio * (containerHeight - thumbHeight);
  scrollThumb.style.top = `${thumbTop}px`;
}

// 监听滚动、resize事件
scrollContainer.addEventListener('scroll', updateScrollbar);
window.addEventListener('resize', updateScrollbar);

// 初始化滚动条
updateScrollbar();

// 实现拖拽滚动
let isDragging = false;
let startY = 0;
let startScrollTop = 0;

scrollThumb.addEventListener('mousedown', (e) => {
  isDragging = true;
  startY = e.clientY;
  startScrollTop = scrollContainer.scrollTop;
  document.body.style.userSelect = 'none';
});

document.addEventListener('mousemove', (e) => {
  if (!isDragging) return;
  const deltaY = e.clientY - startY;
  const containerHeight = scrollContainer.clientHeight;
  const contentHeight = scrollContainer.scrollHeight;
  const thumbHeight = scrollThumb.offsetHeight;
  const scrollDelta = (deltaY / (containerHeight - thumbHeight)) * (contentHeight - containerHeight);
  scrollContainer.scrollTop = startScrollTop + scrollDelta;
});

document.addEventListener('mouseup', () => {
  isDragging = false;
  document.body.style.userSelect = '';
});

关键说明:

  • 隐藏原生滚动条,通过自定义元素模拟滚动条,样式和交互完全可控。
  • 监听滚动、resize事件同步滚动条位置,支持拖拽滚动,体验接近原生。
  • 兼容所有现代浏览器,包括Firefox、Edge、Chrome等。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 20:56:00