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

如何用CSS和JavaScript实现滚动列表的居中吸附效果

垂直滚动列表居中吸附解决方案

一、纯CSS修正方案

你之前的CSS方案未生效,核心问题是滚动容器(ul)缺少明确的高度和滚动属性——scroll-snap必须依赖有可滚动区域的容器才能正常工作。以下是修正后的完整代码:

修正后CSS代码

.wrapper {
  width: 100vw;
  height: 100vh;
  background-color: #e5ddde;
  display: flex;
  justify-content: center;
  overflow: hidden; /* 隐藏容器外溢出内容 */
}

li {
  text-transform: uppercase;
  font-family: Futura;
  font-size: 40px;
  color: grey;
  scroll-snap-align: center; /* 核心吸附规则:项居中对齐容器 */
  margin: 80px 0; /* 添加间距,确保居中视觉效果清晰 */
}

li.active {
  color: black;
}

ul {
  list-style: none;
  padding: 0;
  margin: 0;
  height: 100%; /* 让容器高度匹配父级,形成滚动区域 */
  overflow-y: auto; /* 开启垂直滚动 */
  scroll-snap-type: y mandatory; /* 强制滚动停止时吸附到最近项 */
  scroll-behavior: smooth; /* 可选:添加平滑滚动过渡 */
  scrollbar-width: none; /* 隐藏滚动条(可选) */
}

ul::-webkit-scrollbar {
  display: none; /* 适配webkit内核浏览器隐藏滚动条 */
}

关键修正点

  • 给ul设置height: 100%和overflow-y: auto,明确可滚动区域
  • 给列表项添加上下间距,避免项与项过度紧凑,强化居中吸附的视觉感知
  • 清除列表默认的内外边距,避免布局偏移
  • 可选添加scroll-behavior: smooth优化过渡体验

如果纯CSS方案仍存在边缘场景问题(如旧浏览器兼容性、自定义交互需求),可以用JavaScript实现更精准的控制。

二、JavaScript实现方案

通过监听滚动事件,计算最近列表项的位置,手动调整滚动位置实现居中吸附,同时支持自定义交互逻辑。

完整代码示例

HTML(保持不变)

<div class="wrapper">
  <ul>
    <li>Name One</li>
    <li>Name Two</li>
    <li>Name Three</li>
    <li class="active">Name Four -----</li>
    <li>Name One</li>
    <li>Name Two</li>
    <li>Name Three</li>
    <li>Name Four</li>
    <li>Name One</li>
    <li>Name Two</li>
    <li>Name Three</li>
    <li>Name Four</li>
    <li>Name One</li>
    <li>Name Two</li>
    <li>Name Three</li>
    <li>Name Four</li>
  </ul>
</div>

CSS(基础布局)

.wrapper {
  width: 100vw;
  height: 100vh;
  background-color: #e5ddde;
  display: flex;
  justify-content: center;
  overflow: hidden;
}

li {
  text-transform: uppercase;
  font-family: Futura;
  font-size: 40px;
  color: grey;
  margin: 80px 0;
}

li.active {
  color: black;
}

ul {
  list-style: none;
  padding: 0;
  margin: 0;
  height: 100%;
  overflow-y: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
}

ul::-webkit-scrollbar {
  display: none;
}

JavaScript代码

const listContainer = document.querySelector('ul');
const listItems = Array.from(document.querySelectorAll('li'));
let scrollTimeout;

// 计算让最近项居中的目标滚动位置
function getTargetScrollTop() {
  const containerHeight = listContainer.clientHeight;
  const scrollTop = listContainer.scrollTop;
  
  // 遍历找到距离容器中心最近的列表项
  const closestItem = listItems.reduce((prev, curr) => {
    const prevCenter = prev.offsetTop + prev.clientHeight / 2;
    const currCenter = curr.offsetTop + curr.clientHeight / 2;
    const containerCenter = scrollTop + containerHeight / 2;
    
    const prevDistance = Math.abs(prevCenter - containerCenter);
    const currDistance = Math.abs(currCenter - containerCenter);
    
    return currDistance < prevDistance ? curr : prev;
  });
  
  // 计算让该项居中的滚动值
  return closestItem.offsetTop - (containerHeight - closestItem.clientHeight) / 2;
}

// 滚动停止后触发吸附逻辑
listContainer.addEventListener('scroll', () => {
  clearTimeout(scrollTimeout);
  // 滚动停止150ms后执行吸附(可根据需求调整延迟时间)
  scrollTimeout = setTimeout(() => {
    const targetTop = getTargetScrollTop();
    listContainer.scrollTo({ top: targetTop, behavior: 'smooth' });
    
    // 更新active类标记当前居中项
    listItems.forEach(item => item.classList.remove('active'));
    const activeItem = listItems.find(item => {
      const itemCenter = item.offsetTop + item.clientHeight / 2;
      const containerCenter = listContainer.scrollTop + listContainer.clientHeight / 2;
      return Math.abs(itemCenter - containerCenter) < item.clientHeight / 2;
    });
    activeItem?.classList.add('active');
  }, 150);
});

// 页面加载时让默认active项居中
window.addEventListener('load', () => {
  listContainer.scrollTo({ top: getTargetScrollTop(), behavior: 'smooth' });
});

JS方案优势

  • 可自定义吸附触发的延迟时间,适配不同交互场景
  • 精准控制active类的切换逻辑
  • 兼容对scroll-snap支持不佳的旧浏览器
  • 可扩展更多自定义交互(如滚动时的项高亮动画)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:17:30