场景:
使用表格组件的时候,我们为表格设置height:100%,当数据超出可视区域时,会显示纵向滚动条,可以做到不携带表头的滚动。但这也存在一个问题,纵向滚动条的出现会导致我们的列宽受到挤压从而出现横向滚动条,这是不够美观的,效果如下图:
那应该如何解决这个问题呢?
有一种说法是为表格内的列设置min-width或max-width,如果本身我们只想列自适应宽,而不想去固定某个值的时候,这并不能很好的解决挤压的问题。此外,如果我们给表格设置overflow-x: hidden;也具有风险,如果是小分辨率,需要横向滚动条的时候又展示不出来了,这里我们可以使用一个新的CSS属性:
让滚动条覆盖而不是“挤压”
scrollbar-gutter: stable both-edges;
不过这个属性需要较新的浏览器才可以支持,注意浏览器的兼容性。
这里我以tinyVue为例进行使用:
.tiny-grid__body-wrapper {
scrollbar-gutter: stable both-edges;
}
实现效果:
补充问题:
在后续使用的过程中,我发现使用 scrollbar-gutter: stable both-edges;的时候会导致列表左右侧出现空白,比如如图的效果:
如果使用 scrollbar-gutter: stable;会在右侧出现空白,左侧可以完整填充,也有scrollbar-gutter: auto;但这个并不能预留空白。如何解决这一问题呢?
可以使用 css+js 结合的方式实现:
给 wrapper 默认用 auto
,当检测到内容溢出(需要滚动)时,加个类改成 stable
.tiny-grid__body-wrapper {
scrollbar-gutter: auto;
}
.tiny-grid__body-wrapper.has-scroll {
scrollbar-gutter: stable;
}
// 为表格绑定 ref="gridRef",以 tiny-grid 为例
<tiny-grid ref="gridRef" ... />
let wrapper
const gridRef = ref(null)
const updateGutter = () => {
if (wrapper.scrollHeight > wrapper.clientHeight) {
wrapper.classList.add('has-scroll')
} else {
wrapper.classList.remove('has-scroll')
}
}
const useGutter = () => {
updateGutter()
window.addEventListener('resize', updateGutter)
}
const getData = () => {
// ...获取到新的数据之后,调用 useGutter 更新状态
nextTick(() => { // 这里要放在 nextTick 里面才能保证正确更新
useGutter()
})
}
onMounted(() => {
wrapper = gridRef.value?.$el.querySelector('.tiny-grid__body-wrapper')
getData() // 获取页面数据的方法
});