zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

纯CSS实现拖拽--resize、scale、包裹性

2023-04-18 16:49:44 时间

Thinking系列,旨在利用10分钟的时间传达一种可落地的编程思想或解决方案。

今天看了一篇关于 CSS 的文章,文章用到的几个点,想和大家聊聊。 附「原文地址」大家可自己查阅。

原文题目:CSS 奇思妙想 | 使用 resize 实现强大的图片拖拽切换预览功能 原文地址:https://www.cnblogs.com/coco1s/p/15151338.html 示例源码:https://codepen.io/Chokcoco/pen/bGqWJZL

<div class='picA'>
    <div class='picB'>
        <div readonly class='resizeElement'>div>
    div>
div>

该示例,通过纯 css 实现了图片拖拽切换功能,没有涉及任何的 JavaScript 代码,着实有些“奇思妙想”。

resize

提到的第一个点,一定是 resize 属性,这个属性在平时开发中很少用到。其可由用户调整元素的尺寸大小。配合容器的 max-widthmin-widthmax-heightmin-height 限制可拖拽改变的范围。

属性值

说明

none

不可以缩放

both

水平和垂直方向上均可调整元素的大小

horizontal

在水平方向上调整元素的大小

vertical

在垂直方向上调整元素的大小

注意: 块元素 overflow 属性不能设置为 visible。

overflow 指定除 visible (默认值)以外的值(hidden/scroll/auto)将创建一个新的 块级格式化上下文(BFC)。这在技术层面上是必须的——如果一个浮动元素和滚动条相交,它会在每个滚动步骤后强行重新包装内容,从而导致慢滚动体验。

.resizable {
  resize: both;
  overflow: scroll;
}
<div class="resizable">div>
<textarea class="resizable">textarea>

开头示例中用到的地方:

.resizeElement {
  resize: horizontal;
  overflow: scroll;
  /* 控制可拖拽的范围 */
  min-width: 15px;
  max-width: 650px;  
}

scale

对相关元素设置 resize 后,会在元素右下角添加操作柄,但整体操作区域比较小,非常不方便。像上述示例gif图中所展示,需要增大整个展示区域该如何操作?

.resizeElement {
  position: relative;
  top: 50%;
  left: 0;
  height: 15px;
}

元素居于 picB 的中间位置,高度15(操作柄在右侧),通过 scaleY() 来放大操作区域

scaleY() 函数定义了一个沿 y 轴(垂直)调整元素大小的变换。

.resizeElement {
  opacity: 0;
	transform: scaleY(25);
  transform-origin: center center;
}

通过上述操作,操作区域变成整个区域的右侧。

显示拖拽条

由于完全隐藏了滚动条,用户也就不知道可以拖拽了,所以我们还需要绘制一个更为好看的拖拽条。通过伪元素实现:

.picB:before {
    content: "↔";
    position: absolute;
    background: rgba(0, 0, 0, 0.5);
    font-size: 16px;
    color: white;
    top: 0;
    right: 0;
    height: 100%;
    line-height: 340px;
}

操作区域的的透明度为0,实际还是操作的 resizeElement

收缩与包裹

width 默认值为 auto,其有4种不同的表现:

  • 充分利用空间: 的宽度默认是100%于父级容器的;
  • 收缩与包裹:浮动、绝对定位(absolute、fixed)、inline-block 元素或 table 元素;
  • 收缩到最小:table-layout 为 auto 的表格中。中文是随便断的,英文单词不能断;
  • 超出容器限制:内容很长的连续英文和数字,或者元素被设置了white-space: nowrap

格式化宽度: 绝对定位(absolute、fixed)的元素,默认情况下宽度表现是“包裹性”,宽度由内部尺寸决定。当 left/right、top/bottom 对立方位的属性同时存在时,宽度表现是“格式化宽度”,宽度大小相对于最近的具有定位特性(非static)的祖先元素计算。格式化宽度具有完全的流体性。

包裹性: 元素尺寸由内部元素决定,但永远小于“包含块”容器的尺寸。inline-block元素、浮动元素以及绝对定位元素都具有包裹性!

示例:文字少居中显示;文字超过一行居左展示。

<style>
  .box {
    width: 300px;
    height: 100px;
    border: 1px solid red;
    text-align: center;
  }
  .content {
    display: inline-block;
    text-align: left;
  }
style>
<div class="box">
	<div class="content">纸上得来终觉浅,绝知此事要躬行div>
div>

.box{text-align: center;} 决定了 $('.content')的水平对齐方式为居中对齐; .content{text-align: left;}决定了文字的水平对齐方式为居左。

利用 inline-block 的包裹特性即可实现:内容少,宽度自适应(文字left–撑满元素,元素center);超过一行,$('.content') 的宽度为父容器宽度300px(文字left,元素center–撑满父元素)。

开头示例中用到的地方:

.picB {
  position: absolute;
}

这里充分利用了包裹性,子元素 ('.resizeElement') 的变化会影响父元素 ('.picB') 的改变。从而实现操作子元素来实现父元素的切换。