基于display:grid的可拖拽滚动元素:适配可变可见项数量
Grid布局无法左右滚动的原因及修复方案
问题原因
- Grid列自适应收缩:
.bottom容器用grid-template: auto / auto auto auto auto auto auto auto定义列,Grid默认会收缩列宽以适配容器的100vw宽度,导致子元素设置的宽度被覆盖,容器不会产生横向溢出,无法触发左右滚动。 - Overflow属性错误:
.bottom设置overflow:hidden,既隐藏了溢出内容,也未明确开启横向滚动支持。 - 拖拽逻辑冗余:JS中对
event.movementX正负值的判断重复,代码可以简化。
修复步骤
1. 调整Grid容器配置,允许横向溢出
修改.bottom的CSS,强制列宽不收缩,并开启滚动:
.bottom { width: 100vw; height: 100vh; display: grid; /* 用repeat+minmax强制列宽为计算值,禁止收缩 */ grid-template-columns: repeat(7, minmax(calc(100vw / 7), auto)); /* 允许横向、纵向滚动 */ overflow: auto; user-select: none; }
2. 修正媒体查询的布局逻辑
在窄屏(宽高比<1)时切换为6列布局,无需单独设置子元素宽度:
@media (max-aspect-ratio: 1/1) { .bottom { grid-template-columns: repeat(6, minmax(calc(100vw / 6), auto)); } }
3. 简化拖拽交互逻辑
合并重复判断,优化代码:
var element = document.getElementById('bottom'); element.addEventListener("mousemove", function(event) { if (event.buttons !== 1) return; if (Math.abs(event.movementX) > Math.abs(event.movementY)) { element.scrollLeft -= event.movementX; } else { element.scrollTop -= event.movementY; } });
4. 移除冗余的子元素宽度
删除.div类中的width:25vw,避免与Grid列定义冲突:
.div { height: 25vh; }
完整修复代码
HTML
<body> <div class="bottom" id="bottom"> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> <div class="div yellow"></div> <div class="div white"></div> </div> </body>
CSS
body { background: #046; margin: 0; padding: 0; overflow: hidden; } .bottom { width: 100vw; height: 100vh; display: grid; grid-template-columns: repeat(7, minmax(calc(100vw / 7), auto)); overflow: auto; user-select: none; } .yellow { background: yellow; } .white { background: white; } .div { height: 25vh; } @media (max-aspect-ratio: 1/1) { .bottom { grid-template-columns: repeat(6, minmax(calc(100vw / 6), auto)); } }
JS
var element = document.getElementById('bottom'); element.addEventListener("mousemove", function(event) { if (event.buttons !== 1) return; if (Math.abs(event.movementX) > Math.abs(event.movementY)) { element.scrollLeft -= event.movementX; } else { element.scrollTop -= event.movementY; } });
内容的提问来源于stack exchange,提问作者Escape75
相关产品推荐
相关产品推荐

