大家会用什么样的方式实现上方的元素拉伸效果呢?
是监听鼠标事件,然后与clientHeight、offsetHeight、scrollHeight这些高度纠缠不清,还是选择更加省事且优雅的方法呢?
试试CSS的resize属性吧!
| resize取值 | 说明 |
|---|---|
| none | 设置了resize: none;之后,元素将不受任何调整尺寸的控制 |
| horizontal | 元素可以被用户沿水平方向调整尺寸 |
| vertical | 元素可以被用户沿垂直方向调整尺寸 |
| both | 元素可以被用户任意调整尺寸,不限于水平方向与垂直方向 |
需要注意的是,resize无法作用于内联元素以及被
overflow: visible;作用的块元素
现在我们通过实现上面的拉伸效果,来学习一下如何使用resize。
核心思路
通过给需要拉伸的元素套一层父容器,并添加一个用于拉伸的兄弟元素,拉伸兄弟元素使其撑开父容器,自身高度继承父容器的高度。流程如下
graph LR
拉伸兄弟元素 --> 撑开父元素 --> 自身跟随父元素高度撑开
<!-- 父容器container -->
<div class="container">
<!-- 用于拉伸的兄弟元素resize -->
<div class="resize"></div>
<!-- 用于展示的容器 -->
<div class="current"></div>
</div>
设置resize
我们需要为兄弟元素设置一个拉伸区,为了实现上下拉伸的效果,因此为其设置resize: vertical;,并且为其设置一个初始高度撑开父容器。
.resize {
overflow: scroll;
resize: vertical;
height: 100px;
}
我们注意到,为了告诉CSS这个容器不是
overflow: visible;,我们为此设置了一个overflow: scroll;。当然,你想设置成hidden或auto也是可以的,但在这里设置成scroll会更好,具体原因后面再讲。
至此,我们已经得到了一个可以上下拉伸的盒子了。
脱离文档流
由于只需要兄弟元素撑开父容器,但又需要自身元素高度跟随父容器的高度变化而变化,因此还需要相对于父容器做绝对定位脱离文档流。
.container {
position: relative;
.current {
position: absolute;
top: 0;
left: 0;
right: 0;
overflow: hidden;
height: calc(100% - 7px);
}
}
我们继承了父容器高度的同时还减去了7px,这其实是拉伸热区的高度
为了更好的演示效果,我们为current增添些东西。
<div class="current">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
<p>8</p>
</div>
效果如下:
翻转与热区
我们发现,现在这个热区太小了,并且还在元素的底部!
怎么设置元素拉伸热区的大小?其实可以通过设置滚动条的大小来设置。
.resize {
// 此处省略其他代码
&::-webkit-scrollbar {
width: 100px; // 设置热区的宽度为100px
}
}
还记得上文提到的
overflow: scroll;吗?如果不设置成scroll,将无法正常为热区设置大小。
接下来,我们需要将热区转移到顶部,这很简单,使用CSS3的transform来解决。
.resize {
// 此处省略其他代码
transform: rotateX(180deg);
}
此时我们发现,热区与current重合了。因此我们需要调整一下current的样式,那便是————将其往下移出相应热区的高度。还记得我们对其进行了文档流的脱离吗,我们只需要调整一下top的值就行了。
.current {
// 其余代码省略
top: 7px;
}
热区太丑了?使用障眼法隐藏一下~
.resize {
// 此处省略其他代码
opacity: 0;
}
向上拉伸
可以看看目前的效果,实在是太怪了!
我们需要元素跟随鼠标向上拉伸,而不是元素与鼠标南辕北辙!
来吧!让我们再为父容器设置一个父容器,即爷爷容器,并让父容器触底于爷爷容器,阻止其往下拉伸。
<div class="can_drag_container">
<div></div>
<div class="container">
<!-- 其余代码省略 -->
</div>
</div>
.can_drag_container {
height: 500px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
完整代码