使用resize属性实现元素拖拉改变宽度
1.背景
地图页面左侧全量树新需求,想要实现左侧树的拖拉效果,方便用户使用。
查阅资料发现使用js逻辑,通过监听鼠标按下、移动、抬起事件等进行处理可以实现,但是考虑到地图页面的性能已经吃不消了,于是不使用此方法实现。
之前看过相关css中的resize属性使用的文章,查看有关博客感觉可以实现元素的拖拉效果,于是使用resize属性进行功能实现。
2.小demo热身
参考了张鑫旭老师的纯CSS实现分栏宽度拉伸调整demo。
https://www.zhangxinxu.com/study/201903/css-idea/behavior-stretch.php?aside=0
自己动手试了一下,发现了一些小问题,示例如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html, body {
height: 100%;
}
.box {
display: flex;
overflow: hidden;
height: 100%;
}
.left, .right {
height: 100%;
position: relative;
}
.left-reisze {
width: 200px;
height: inherit;
resize: horizontal;
overflow: scroll;
cursor: col-resize;
opacity: 0;
}
.resize-save {
position: absolute;
top: 0; right: 8px; bottom: 0; left: 0;
padding: 16px;
overflow-x: hidden;
}
.resize-line {
position: absolute;
width: 4px;
right: 0; top: 0; bottom: 0;
border-right: 2px solid #eee;
border-left: 1px solid #bbb;
pointer-events: none;
}
.left-reisze:hover ~ .resize-line,
.left-reisze:active ~ .resize-line {
border-left: 1px dashed skyblue;
}
.left-reisze::-webkit-scrollbar {
width: 200px;
height: inherit;
}
</style>
</head>
<body>
<div class="box">
<div class="left">
<div class="left-reisze"></div>
<div class="resize-line"></div>
<div class="resize-save">Left</div>
</div>
<div class="right">Right</div>
</div>
</body>
</html>
发现当父容器left
的height
设置为100%
时,webkit-scrollbar
的高度设置为inherit
时不生效,感觉高度变为0了。只有父容器left
设置为固定高度时,webkit-scrollbar
的高度设置为inherit
时才能正常继承。
这里有个简单的解决方法,不考虑大屏展示时可以给webkit-scrollbar
设置个固定高度2000px,考虑大屏展示再设置大一些。
还有个解决方法,要结合js使用,强行塞个高度。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html, body {
height: 100%;
}
.box {
display: flex;
overflow: hidden;
height: 100%;
}
.left, .right {
height: 100%;
position: relative;
}
.left-reisze {
width: 200px;
// max-width: 750px; 这里可以设置最大、最小拖拉宽度
height: inherit;
resize: horizontal;
overflow: scroll;
cursor: col-resize;
opacity: 0;
}
.resize-save {
position: absolute;
top: 0; right: 4px; bottom: 0; left: 0;
padding: 16px;
overflow-x: hidden;
}
.resize-line {
position: absolute;
width: 4px;
right: 0; top: 0; bottom: 0;
border-right: 2px solid #eee;
border-left: 1px solid #bbb;
pointer-events: none;
}
.left-reisze:hover ~ .resize-line,
.left-reisze:active ~ .resize-line {
border-left: 1px dashed skyblue;
}
.left-reisze::-webkit-scrollbar {
width: 200px;
height: inherit;
}
</style>
</head>
<body>
<div class="box">
<div class="left">
<div class="left-reisze"></div>
<div class="resize-line"></div>
<div class="resize-save">Left</div>
</div>
<div class="right">Right</div>
</div>
<script>
const node = document.querySelector('.left')
node.setAttribute('style',`height:${node.clientHeight}px`)
</script>
</body>
</html>
3.项目上使用
项目上使用的布局与上面的demo
类似,只是在使用js处理webkit-scrollbar
的高度时监听了浏览器的reisze
事件。
mounted() {
this.updateHeight();
window.onresize = () => {
this.$nextTick(() => {
this.updateHeight();
});
};
},
updateHeight() {
const node = document.querySelector('.rel-tree');
node.setAttribute('style', '');
this.$nextTick(() => {
node.setAttribute('style', `height:${node.clientHeight}px`);
});
},
4.注意点
1.resize-save
盒子中内容超出left
盒子宽度时,会被遮盖
.test {
width: 400px;
height: 400px;
background-color: pink;
}
<div class="box">
<div class="left">
<div class="left-reisze"></div>
<div class="resize-line"></div>
<div class="resize-save">
Left
<div class="test"></div>
</div>
</div>
<div class="right">Right</div>
</div>
2.绝对定位问题
在resize-save
绝对定位盒子中的元素,使用绝对定位时,当超出left
盒子显示区域时发现会被遮挡不可见,怎么改变z-index
都无法全部显示,类似上面的第一种情况,有点不知道原因,这里的解决方式是改用了fixed
固定定位。
3.滚动条无限滚动问题
就是横向滚动条进行滚动时,滚的没完没了了,分明内容滚到底了,但是还能横向滚动,此时页面上展示的全是空白内容。
这是一个无法理解的问题,使用中没碰到正好,碰到时可以使用一个骚操作解决。我的理解是resize-save
盒子的right为4px
,给有滚动条的元素设置宽度是不直接设置100%,而是设置为width:calc(100% + 4px);
,让此滚动元素与left
盒子宽度相同或者大于left
盒子宽度,就解决了,不知道问题的所在。