如何实现响应式选项卡点击<li>自动水平滚动到对应位置(不使用sliderjs)
问题修复方案
两个问题的核心原因
- 变量作用域问题:你用
var声明了parentPos、childPos这类变量,存在变量提升,循环结束后所有点击事件绑定的回调引用的都是最后一次循环的变量值,所以所有子元素计算出来的偏移量都相同。同时getBoundingClientRect()获取的是元素相对于浏览器视口的位置,不是相对于滚动父容器的内部相对位置,计算逻辑本身有误。 - 滚动逻辑问题:你用了
scrollBy做相对滚动,没有结合父容器当前已滚动的距离、以及选中元素是否在可视区域外的判断,所以只能单向滚动。
修复后的代码
1. 先修改CSS的错误配置
原来的.namsaService_tab宽度写死为800px,和父容器宽度一致,不会触发横向溢出滚动,需要修改:
.namsaService_tab { /* 把原来的width:800px替换成下面的 */ width: max-content; white-space: nowrap; }
2. 替换原有JS代码
const tabWrap = document.querySelector('.namsaService_tabContainer') const tabList = document.querySelectorAll('.namsaService_tabList') tabList.forEach(item => { item.addEventListener('click', function (e) { e.preventDefault() // 先移除其他项的选中态,给当前点击项加选中态 tabList.forEach(t => t.classList.remove('on')) this.classList.add('on') // 计算父容器和当前点击项的位置 const wrapRect = tabWrap.getBoundingClientRect() const itemRect = this.getBoundingClientRect() // 计算需要滚动的偏移值:当前元素相对于父容器的左偏移 + 父容器已经滚动的距离 - 20px左侧留白(如果要居中可以改成 (wrapRect.width - itemRect.width)/2 ) const scrollLeft = itemRect.left - wrapRect.left + tabWrap.scrollLeft - 20 // 直接滚动到目标位置,自动支持左右滚动 tabWrap.scrollTo({ top: 0, left: scrollLeft, behavior: 'smooth' }) }) })
实现效果说明
- 点击任意选项卡,自动将该选项卡滚动到可视区域左侧,调整计算参数可适配居中对齐需求
- 自动支持左右双向滚动,无需额外判断方向
- 点击时实时计算位置,避免页面resize后位置计算错误的问题
内容的提问来源于stack exchange,提问作者Hailey
相关产品推荐
相关产品推荐

