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

如何用JavaScript实现不同高度多列异速滚动且底部均匀对齐

实现思路

1. 统一滚动入口,避免多事件冲突

放弃给每个列单独绑定滚动事件的方案,改为仅监听父容器.portfolio-grid的滚动行为,同时把三个.column的overflow属性改为hidden,禁止列自身的滚动能力,从根源上避免多滚动事件互相触发、嵌套执行的问题。

2. 按比例映射滚动距离

通过滚动比例联动各列的位置,保证同时触底:

  • 计算父容器的最大可滚动距离:父容器滚动距离上限 = 父容器scrollHeight - 父容器clientHeight
  • 计算每列的最大可滚动距离:单列滚动距离上限 = 列scrollHeight - 列clientHeight
  • 父容器滚动时,先计算当前滚动比例:滚动比例 = 父容器当前scrollTop / 父容器滚动距离上限
  • 每列的scrollTop直接赋值为:单列scrollTop = 滚动比例 * 单列滚动距离上限
    这个逻辑天然满足「高度越高的列滚动速度越慢」的需求:总高度越高的列,单列滚动距离上限越大,相同滚动比例下滚动的总距离更长,但和父容器滚动的速度比值更小,符合预期。

3. 性能优化

用requestAnimationFrame包裹列scrollTop的更新逻辑,避免滚动事件高频触发时的不必要DOM操作,降低性能损耗。
如果列内图片是动态加载的,需要在所有图片加载完成后重新计算各列的最大滚动距离,避免高度计算错误。

代码实现

修改后的CSS

.column{
    /* 关闭列自身滚动 */
    overflow: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    height: 100%;
    background-color: #468189;
    float: left;
    width: 33.33%;
    padding-right: 10px;
    box-sizing: border-box;
}

.portfolio-grid{
    overflow: auto;
    /* 可以根据实际布局调整高度,保证有滚动空间 */
    height: 100vh; 
    width: 80%;
}

修改后的JavaScript

const grid = document.querySelector('.portfolio-grid')
const columns = document.querySelectorAll('.column')
// 存储各列的最大滚动距离
let colMaxScroll = []
let gridMaxScroll = 0

// 计算所有高度参数的函数,动态内容加载完成后需要重新调用
function calcScrollParams() {
  gridMaxScroll = grid.scrollHeight - grid.clientHeight
  colMaxScroll = Array.from(columns).map(col => col.scrollHeight - col.clientHeight)
  // 把父容器的滚动高度撑到和最高列的可滚动高度匹配,保证能滚到100%比例
  const maxColScroll = Math.max(...colMaxScroll)
  const spacer = document.createElement('div')
  spacer.style.height = `${maxColScroll}px`
  // 先删除旧的占位元素再添加新的
  grid.querySelector('.grid-spacer')?.remove()
  grid.appendChild(spacer)
  spacer.classList.add('grid-spacer')
  // 重新计算父容器最大滚动距离
  gridMaxScroll = grid.scrollHeight - grid.clientHeight
}

// 滚动更新逻辑
function updateColScroll() {
  const ratio = grid.scrollTop / gridMaxScroll
  columns.forEach((col, index) => {
    col.scrollTop = ratio * colMaxScroll[index]
  })
}

// 监听滚动,用requestAnimationFrame优化性能
grid.addEventListener('scroll', () => {
  requestAnimationFrame(updateColScroll)
})

// 初始化计算,动态内容加载完成后需要手动调用calcScrollParams()
calcScrollParams()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:18:03