还在用JS拉伸元素吗?试试CSS吧!

255 阅读3分钟

resize.gif

大家会用什么样的方式实现上方的元素拉伸效果呢?

是监听鼠标事件,然后与clientHeightoffsetHeightscrollHeight这些高度纠缠不清,还是选择更加省事且优雅的方法呢?

试试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;。当然,你想设置成hiddenauto也是可以的,但在这里设置成scroll会更好,具体原因后面再讲。

至此,我们已经得到了一个可以上下拉伸的盒子了。

resize2.gif

脱离文档流

由于只需要兄弟元素撑开父容器,但又需要自身元素高度跟随父容器的高度变化而变化,因此还需要相对于父容器做绝对定位脱离文档流。

.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>

image.png

效果如下:

resize3.gif

翻转与热区

我们发现,现在这个热区太小了,并且还在元素的底部!

image.png

怎么设置元素拉伸热区的大小?其实可以通过设置滚动条的大小来设置。

.resize {
    // 此处省略其他代码
    &::-webkit-scrollbar {
        width: 100px; // 设置热区的宽度为100px
    }
}

image.png

还记得上文提到的overflow: scroll;吗?如果不设置成scroll,将无法正常为热区设置大小。

接下来,我们需要将热区转移到顶部,这很简单,使用CSS3的transform来解决。

.resize {
    // 此处省略其他代码
    transform: rotateX(180deg);
}

image.png

此时我们发现,热区与current重合了。因此我们需要调整一下current的样式,那便是————将其往下移出相应热区的高度。还记得我们对其进行了文档流的脱离吗,我们只需要调整一下top的值就行了。

.current {
    // 其余代码省略
    top: 7px;
}

image.png

热区太丑了?使用障眼法隐藏一下~

.resize {
    // 此处省略其他代码
    opacity: 0;
}

image.png

向上拉伸

可以看看目前的效果,实在是太怪了!

resize4.gif

我们需要元素跟随鼠标向上拉伸,而不是元素与鼠标南辕北辙!

来吧!让我们再为父容器设置一个父容器,即爷爷容器,并让父容器触底于爷爷容器,阻止其往下拉伸。

<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;
}

resize5.gif

完整代码

兼容性

resize的兼容性(包含移动端)

image.png