根本原因是Layui对.fixed列scrollLeft同步进行了50ms节流,导致滚轮滚动时视觉不同步;需在done回调中监听原生scroll事件并实时赋值,同时处理左右固定列及移动端touch兼容。
固定列在滚轮滚动时出现细微延迟抖动,根本原因是 .layui-table-fixed 和 .layui-table-body 两个容器的 scrollleft 同步不及时——layui 默认只在鼠标抬起(mouseup)或滚动结束时批量同步,中间过渡帧被跳过。
为什么滚轮滚动时 fixed 列会“卡一下”才跟上
鼠标滚轮触发的是连续 scroll 事件,但 Layui 的固定列同步逻辑被节流了(内部用 layui.debounce 包裹),默认延迟约 50ms 才更新右侧/左侧固定容器的 scrollLeft。人眼对 16ms 帧率敏感,这个延迟就表现为“先滑动、后追上”的抖动。
- 不是 CSS 动画问题,禁用
transition也无效 - 不是浏览器兼容性问题,Chrome/Firefox/Edge 均存在
- 仅在使用
fixed: 'left'或fixed: 'right'时出现,普通表格无此现象
手动监听 scroll 并实时同步 scrollLeft
绕过 Layui 内置节流,直接绑定原生 scroll 事件,拿到 .layui-table-body 的 scrollLeft 后立刻赋给 .layui-table-fixed-l 和 .layui-table-fixed-r。
- 必须在
done回调里操作,确保 DOM 已渲染完成 - 要同时处理左、右固定列:左固定列需设
scrollLeft = 0(它不随滚动),右固定列才需同步 - 注意判断元素是否存在,避免 Tab 切换后目标 DOM 被销毁又重试报错
table.render({
elem: '#demo',
// ...其他配置
done: function(res, curr, count){
const body = $('.layui-table-body');
const fixedR = $('.layui-table-fixed-r');
const fixedL = $('.layui-table-fixed-l');
body.on('scroll', function(){
if (fixedR[0]) fixedR[0].scrollLeft = this.scrollLeft;
if (fixedL[0]) fixedL[0].scrollLeft = 0; // 左固定列始终锚定左端
});
}
});
防抖失效时的兜底:关闭内置同步并接管
如果项目中已全局修改过 layui.table.setScrollFix 或引入了第三方 patch,可能导致上述监听被覆盖。此时可强制禁用 Layui 自带同步逻辑:
- 在
table.render()前执行layui.table.config.scrollFix = false - 或在
done中移除原有监听:body.off('scroll', layui.table.setScrollFix) - 再挂载你自己的实时监听,避免双写冲突
注意:layui.table.setScrollFix 是私有方法,不保证后续版本兼容,生产环境建议用第一种方式(直接监听 + 赋值)更稳定。
移动端 touchmove 滚动也要单独处理
桌面端滚轮抖动修复后,iOS/Android 上手指拖拽仍可能不同步——因为 touchmove 不触发 scroll 事件,而是靠 transform 位移模拟滚动。
- 需监听
.layui-table-box的touchstart→touchmove→touchend - 在
touchmove中读取getBoundingClientRect().left差值,换算为等效scrollLeft - 更简单做法:给
.layui-table-body加-webkit-overflow-scrolling: touch,让系统接管滚动,再配合上面的scroll监听即可覆盖
真正难的不是写几行同步代码,而是意识到 Layui 的“固定列”本质是三个独立 DOM 容器拼出来的视觉效果——任何一环的尺寸、滚动、渲染时机没对齐,抖动就会从缝隙里漏出来。


















