CSS|
CSS

用CSS3的resize实现拖拽改变大小及分屏

JS实现更多细节

Posted by xzavier on February 11, 2020

前端开发中,可能遇到需要双屏操作或者左右布局可拖拽的需求。

我们可以用一个盒子装两个左右布局的盒子,左边宽度为 w , 则右边宽度为 100% - w 。 动态的改变w值,即可操控两边的盒子宽窄你来我往。怎么改变呢,你可以这样:

  • 1、设计几个按钮,固定的点选左右盒子宽度比;
  • 2、使用 <input type="range" id="rang-slider" name="rang-slider" min="0" max="100" step="5"> 控制w的值,从而控制 100% - w 的值;
  • 3、CSS3的 resize 属性都用过吧,textarea里相信都认识过,用它也阔以实现。

还有计算拖拽鼠标位置用于控制的,既然今天的主角是CSS3的 resize ,那就不走远了,直接上:

Demo

CSS3的resize拖拽

鼠标移到左右盒子中间的虚线就会出现左右拖拽鼠标样式了,下方盒子底部虚线出现上下拖拽鼠标样式。

Code

<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'/>
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache"/>
<meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache"/>
<meta HTTP-EQUIV="Expires" CONTENT="0"/>
<meta http-equiv="x-dns-prefetch-control" content="on"/>
<meta name="description" content="CSS3 resize 拖拽">
<meta name="keywords"  content="CSS3 resize 拖拽">
<meta name="author" content="Xzavier">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
<link rel="Shortcut Icon" href="https://xiaohuazheng.github.io/img/favicon.ico"/>
<title>CSS3-resize拖拽</title>
<style type="text/css">
    body {
        margin: 0;
    }
    h3 {
        padding: 20px 0 0 20px;
        margin: 0;
    }
    .fl {
        float: left;
    }
    .resize-box {
        overflow: hidden;
        background: #f5f5f5;
    }
    .resize-box-left {
        height: 340px;
        position: relative;
    }
    .resize-box-vertical {
        position: relative;
    }
    .l-container {
        background: #fff;
        height: 100%;
        width: 100%;
    }
    .resize-box-right {
        height: 300px;
        padding: 20px;
        overflow: hidden;
    }
    .r-container {
        background: #fff;
        height: 100%;
        width: 100%;
    }
    .resize-real-box {
        position: absolute;
        top: 20px; 
        left: 20px;
        bottom: 20px;
        right: 20px;
        overflow-x: hidden;
    }
    .textarea-box {
        padding: 20px;
        overflow: hidden;
    }
    .textarea-box textarea {
        max-width: 200px;
        max-height: 200px;
    }
    .resize-bar {
        width: 100%; 
        height: inherit;
        opacity: 0;
        overflow: scroll;
    }
    .horizontal {
        resize: horizontal;
        cursor: col-resize;
    }
    .vertical {
        resize: vertical;
        cursor: row-resize;
    }
    .limit-horizontal {
        min-width: 200px;
        max-width: 800px;
    }
    .limit-vertical {
        min-height: 100px;
        max-height: 300px;
    }
    .dividing-line-horizontal {
        position: absolute;
        right: 0; 
        top: 20px; 
        bottom: 20px;
        border-left: 1px solid #ddd;
        pointer-events: none;
    }
    .horizontal:hover ~ .dividing-line-horizontal,
    .horizontal:active ~ .dividing-line-horizontal {
        border-left: 1px dashed skyblue;
    }
    .horizontal::-webkit-scrollbar {
        width: 20px; 
        height: inherit;
    }

    .dividing-line-vertical {
        position: absolute;
        left: 0; 
        right: 0;
        bottom: 10px; 
        border-bottom: 1px solid #ddd;
        pointer-events: none;
    }
    
    .vertical:hover ~ .dividing-line-vertical,
    .vertical:active ~ .dividing-line-vertical {
        border-bottom: 1px dashed skyblue;
    }
    .vertical::-webkit-scrollbar {
        width: 100%; 
        height: 20px;
    }
</style>
</head>
<body>
<h3>resize: horizontal</h3>
<div class="resize-box" style="margin-top: 20px;">
    <div class="resize-box-left fl">
        <div class="resize-bar horizontal limit-horizontal"></div>
        <div class="dividing-line-horizontal"></div>
        <div class="resize-real-box">
            <div class="l-container"></div>
        </div>
    </div>
    <div class="resize-box-right">
        <div class="r-container">
            <div class="textarea-box">
                <textarea></textarea>
            </div>
        </div>
    </div>
</div>
<h3>resize: vertical</h3>
<div class="resize-box" style="margin-top: 20px;">
    <div class="resize-box-vertical">
        <div class="resize-bar vertical limit-vertical"></div>
        <div class="dividing-line-vertical"></div>
        <div class="resize-real-box">
            <div class="l-container"></div>
        </div>
    </div>
</div>

</body>
</html>

resize

巧妙的使用CSS3的resize属性,我们在以前的开发中肯定也遇到过,textarea不想要拖拽改变输入框大小的时候,只需要给盒子的css加上

resize:none;

就可以了。

那我们想要拖拽呢,可以设置 resize 的值为:

both: 可调整盒子的横向宽度和纵向高度
horizontal: 可调整盒子的横向宽度,
vertical: 可调整盒子纵向高度

配上 overflow: scroll; 香!

可是印象中textarea的拖拽只是在右下角一个小小的倒三角:

Demo中的右侧盒子里的textarea

这用在分屏操作上,是不是有点不尽人意,不满足用户的需求呀。

调研发现,webkit浏览器的滚动条可以自定义,而resize区域大小正是scrollbar的大小。

那我们就有的操作了,给加了resize属性的盒子再自定义scrollbar样式:

.resize-bar::-webkit-scrollbar {
    width: 20px; 
    height: inherit;
}

快哉,一下就变得款款的一溜,显然样式被弄得不好看,不打紧,它来帮忙:

opacity: 0;

当然,如果不设置限制,它就会拖拽到边缘,松开手你就没有机会再接触到拖拽的区域了。而且,我们做双屏,大概也不会想把右侧的屏宽度拖为0了吧。如果有这样的需求,那就需要再设计一下了。我们价格限制:

min-width: 200px;
max-width: 800px;

这样你就有了一个左右分屏,可拖拽大小的布局了,见Demo.

你想要纵向拖拽盒子:

resize: vertical;

这样,除了textarea,我们又把resize用到拖拽改变盒子大小和左右分屏了。

以上使用比较适合简单的场景,当我们的场景变得复杂化,产品需求更细腻的时候

input type=”range”

当然,这个属性的设计肯定不是为了做双屏的,当我们想要双屏实现的时候,可以考虑用:

<input type="range" id="rang-slider" name="rang-slider" min="0" max="100" step="5">

我们可以根据range的值手动改变左右盒子的宽度来实现。

ionRangeSlider

实现双屏左右屏大小拖拽改变,我们也阔以借住插件,推荐:ion-rangeslider

然后根据产品的需求或者自己的洗好改变样式就可以很香!