本文为稀土技术社区首发签约文章,14 天内制止转载,14 天后未获授权制止转载,侵权必究!

我的新的专栏 — 现代 CSS 与 Web 动画处理方案

将专心于完成杂乱布局,兼容设备差异,制作酷炫动画,制作杂乱交互,提高可拜访性及构建奇思妙想作用等方面的内容。

在兼顾根底概述的一起,注重对技巧的发掘,结合实践进行运用,欢迎咱们重视。

背景

鼠标拖拽元素移动,算是一个略微有点点杂乱的交互。

而在本文,咱们就将打破常规,向咱们介绍一种超强的只是运用纯 CSS 就能够完成的鼠标点击拖拽作用。

在之前的这篇文章中 — 不可思议的纯 CSS 完成鼠标跟从,咱们介绍了十分多有意思的纯 CSS 的鼠标跟从作用,像是这样:

超强的纯 CSS 鼠标点击拖拽作用

可是,能够看到,上面的作用中,元素的移动不是很丝滑。假如你了解上述的完成办法,就会知道它存在比较大的局限性。

本文,咱们还是只是经过 CSS,来完成一种丝滑的鼠标点击拖动元素移动的作用。

鼠标点击拖拽跟从作用

OK,什么意思呢?咱们先来看一个最最简略的作用示意图,完成点击一个元素,能够拖动元素进行移动的作用:

超强的纯 CSS 鼠标点击拖拽作用

好的,到这儿,在继续往下阅览之前,你能够停一停。这种作用,正常而言,都是必需要凭借 JavaScript 才能够完成的。从表现上来看:

  1. 首要拖拽元素进程,能够任意将元素进行移动
  2. 然后放置元素,让元素停留在别的一个当地

考虑一下,假如不凭借 JavaScript 的话,有办法将元素小球从 A 点移动到 B 点么?这个作用彻底就不像是纯 CSS 能够完成的。

答案必定是能够的!整个进程也十分之奇妙,这儿咱们中心需要运用强壮的 resize 特点。以及,合作经过构建一种奇妙的布局,去处理或许会遇到的各种难题。

运用 resize,构建可拖拽改动巨细的元素

首要,咱们运用 resize 特点来完成一个可改动巨细的元素。

什么是 resize 呢?依据 MDN — resize:该 CSS 特点答应你操控一个元素的可调整巨细性。

其 CSS 语法如下所示:

{
/* Keyword values */
  resize: none;
  resize: both;
  resize: horizontal;
  resize: vertical;
  resize: block;
  resize: inline;
}

简略解释一下:

  • resize: none:元素不能被用户缩放
  • resize: both:答运用户在水平缓笔直方向上调整元素的巨细
  • resize: horizontal:答运用户在水平方向上调整元素的巨细
  • resize: vertical:答运用户在笔直方向上调整元素的巨细
  • resize: block:依据书写形式(writing-mode)和方向值(direction),元素显现答运用户在块方向上(block)水平或笔直调整元素巨细的机制。
  • resize: inline:依据书写形式(writing-mode)和方向值(direction),元素显现一种机制,答运用户在内联方向上(inline)水平方向或笔直方向调整元素的巨细。

看一个最简略的 DEMO:

<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aut qui labore rerum placeat similique hic consequatur tempore doloribus aliquid alias, nobis voluptates. Perferendis, voluptate placeat esse soluta deleniti id!</p>
p {
    width: 200px;
    height: 200px;
    resize: horizontal;
    overflow: scroll;
}

这儿,咱们设置了一个长宽为 200px<p> 为横向可拖拽改动宽度。作用如下:

超强的纯 CSS 鼠标点击拖拽作用

简略总结一些小技巧:

  • resize 的生效,需要合作 overflow: scroll,当然,精确的说法是,overflow 不是 visible,或者能够直接作用于替换元素比如图像、<video><iframe><textarea>
  • 咱们能够经过 resizehorizontalverticalboth 来设置横向拖动、纵向拖动、横向纵向皆可拖动。
  • 能够合作容器的 max-widthmin-widthmax-heightmin-height 限制可拖拽改动的一个范围

这儿,假如你的对 resize 还有所疑惑,或者想了解更多 resize 的风趣用法,能够看看我的这篇文章:CSS 奇思妙想 | 运用 resize 完成强壮的图片拖拽切换预览功用。

将 resize 运用到本文实例中

OK,接下来,咱们将 resize 实践运用到咱们本文的比如中去,首要,咱们先简略完成一个 DIV:

<div class="g-resize"></div>
.g-resize {
    width: 100px;
    height: 100px;
    border: 1px solid deeppink;
}

如下,十分一般,没有什么特别的:

超强的纯 CSS 鼠标点击拖拽作用

可是,经过给这个元素加上 resize: both 以及 overflow: scroll,此刻,这个元素的巨细就经过元素右下角的 ICON 进行拖动改动。

简略修正下咱们的 CSS 代码:

.g-resize {
    width: 100px;
    height: 100px;
    border: 1px solid deeppink;
    resize: both;
    overflow: scroll;
}

这样,咱们就得到了一个灵敏能够拖动的元素:

超强的纯 CSS 鼠标点击拖拽作用

是的,咱们的整个作用,就需要凭借这个特性进行完成。

在此根底上,咱们能够测验将一个元素定位到上面这个可拖动扩大缩小的元素的右下角,看着能不能完成上述的作用。

简略加一点代码:

<div class="g-resize"></div>
.g-resize {
    position: relative;
    width: 20px;
    height: 20px;
    resize: both;
    overflow: scroll;
}
.g-resize::before {
    content: "";
    position: absolute;
    bottom: 0;
    right: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: deeppink;
}

咱们运用元素的伪元素完成了一个小球,放置在容器的右下角看看作用:

超强的纯 CSS 鼠标点击拖拽作用

假如咱们再把整个设置了 resize: both 的边框隐藏呢?那么作用就会是这样:

超强的纯 CSS 鼠标点击拖拽作用

Wow,整个作用现已十分的接近了!只是,仔细看的话,能够看到一些瑕疵,就是还是能够看到设置了 resize 的元素的这个 ICON:

超强的纯 CSS 鼠标点击拖拽作用

这个也好处理,在 Chrome 中,咱们能够经过别的一个伪元素 ::-webkit-resizer ,设置这个 ICON 的隐藏。

依据 MDN – ::-webkit-resizer,它归于整体的滚动条伪类样式宗族中的一员。

其间 ::-webkit-resizer 能够操控出现在某些元素底角的可拖动调整巨细的滑块的样式。

所以,这儿我就运用这个伪类:

.g-resize {
    position: relative;
    width: 20px;
    height: 20px;
    resize: both;
    overflow: scroll;
}
.g-resize::before {
    content: "";
    position: absolute;
    bottom: 0;
    right: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: deeppink;
}
.g-resize::-webkit-resizer {
    background-color: transparent;
}

这样,这儿的中心在于运用了 .g-resize::-webkit-resizer 中的 background-color: transparent,将滑块的色彩设置为了通明色。咱们就得到了与文章一开始,一模一样的作用:

超强的纯 CSS 鼠标点击拖拽作用

处理溢出被裁剪问题

当然,这儿有个很丧命的问题,假如需要移动的内容,远比设置了 resize 的容器要大,或者其初始方位不在该容器内,超出了的部分因为设置了 overflow: scroll,将无法看到。

因此上述方案存在比较大的缺陷。

举个比如,假定咱们需要被拖动的元素不再是一个有这样一个简略的结构:

<div class="g-content"></div>
.g-content {
    width: 100px;
    height: 100px;
    background: black;
    pointer-event: none;
    &::before {
        content: "";
        position: absolute;
        width: 20px;
        height: 20px;
        background: yellow;
        border-radius: 50%;    
}

而像是这样,是一个更为杂乱的布局内容展示(当然下面展示的也比较简略,实践中能够想象成任意杂乱结构内容):

超强的纯 CSS 鼠标点击拖拽作用

假如将这个结构,扔到上面的 g-resize 中:

<div class="g-resize">
    <div class="g-content"></div>
</div>

那么就会因为设置了 overflow: scroll 的原因,将彻底看不到,只剩下一小块:

超强的纯 CSS 鼠标点击拖拽作用

为了处理这个问题,咱们得修正原本的 DOM 结构,另辟蹊径。

办法有许多,比如能够运用 Grid 布局的一些特性。当然,这儿咱们只需要奇妙的加多一层,就能够彻底处理这个问题。

咱们来完成这样一个布局:

<div class="g-container">
    <div class="g-resize"></div>
    <div class="g-content"></div>
</div>

解释一下上述代码,其间:

  1. g-container 设置为肯定定位加上 display: inline-block,这样其盒子巨细就能够由内部正常流式布局盒子的巨细撑开
  2. g-resize 设置为 position: relative 并且设置 resize,负责供给一个可拖动巨细元素,在这个元素的变化进程中,就能动态改动父容器的高宽
  3. g-content 实践内容盒子,经过 position: absolute 定位到容器的右下角即可

看看完好的 CSS 代码:

.g-container {
    position: absolute;
    display: inline-block;
}
.g-resize { 
    content: "";
    position: relative;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    resize: both;
    overflow: scroll;
    z-index: 1;
}
.g-content {
    position: absolute;
    bottom: -80px;
    right: -80px;
    width: 100px;
    height: 100px;
    background: black;
    pointer-event: none;
    &::before {
        content: "";
        position: absolute;
        width: 20px;
        height: 20px;
        background: yellow;
        border-radius: 50%;
        transition: .3s;
    }
}
.g-container:hover .g-content::before {
    transform: scale(1.1);
    box-shadow: -2px 2px 4px -4px #333, -4px 4px 8px -4px #333;
}
.g-resize::-webkit-resizer {
    background-color: transparent;
}

下图中,你看到的一切元素,都只是 g-content 呈现出来的元素,整个作用就是这样:

超强的纯 CSS 鼠标点击拖拽作用

是的,或许你会有所疑惑,下面我用简略不同色彩,标识不同不同的 DOM 结构,方便你去了解。

  1. 赤色边框表明整个 g-container 的巨细
  2. 用蓝色矩形表明设置了 g-resize 元素的巨细
  3. 关掉 ::-webkit-resizer 的通明设置,展示出 resize 框的可拖拽 ICON
.g-container {
    border: 3px solid red;
}
.g-resize { 
    content: "";
    background: blue;
    resize: both;
    overflow: scroll;
}
.g-resize::-webkit-resizer {
    // background-color: transparent;
}

看看这个图,整个原理基本就比较清晰的浮现了出来:

超强的纯 CSS 鼠标点击拖拽作用

完好的原理代码,你能够戳这儿:CodePen Demo — Pure CSS Auto Drag Demo

实践运用

OK,用了比较大篇幅对原理进行了描述。下面咱们举一个实践的运用场景。运用上述技巧制作的可拖动便签贴。创意来自 — scottkellum。

代码也不多,假如你了解了上面的内容,下面的代码将十分好了解:

<div class="g-container">
    <div class="g-resize"></div>
    <div class="g-content"> Lorem ipsum dolor sit amet consectetur?</div>
</div>

完好的 CSS 代码如下:

body {
    position: relative;
    padding: 10px;
    background: url("背景图");
    background-size: cover;
}
.g-container {
    position: absolute;
    display: inline-block;
}
.g-resize {
    content: "";
    position: relative;
    width: 20px;
    height: 20px;
    resize: both;
    overflow: scroll;
    z-index: 1;
}
.g-content {
    position: absolute;
    bottom: -160px;
    right: -180px;
    color: rgba(#000, 0.8);
    background-image: linear-gradient(
        160deg,
        rgb(255, 222, 30) 50%,
        rgb(255, 250, 80)
    );
    width: 200px;
    height: 180px;
    pointer-event: none;
    text-align: center;
    font-family: "marker felt", "comic sans ms", sans-serif;
    font-size: 24px;
    line-height: 1.3;
    padding: 1em;
    box-sizing: border-box;
    &:before {
        content: "";
        position: absolute;
        width: 20px;
        height: 20px;
        top: 0;
        left: 0;
        border-radius: 50%;
        background-image: radial-gradient(
            at 60% 30%,
            #f99,
            red 20%,
            rgb(180, 8, 0)
        );
        background-position: 20% 10%;
        cursor: pointer;
        pointer-events: none;
        transform: scale(0.8);
        box-shadow: -5px 10px 3px -8.5px #000, -1px 7px 12px -5px #000;
        transition: all 0.3s ease;
        transform: scale(0.8);
    }
}
.g-container:hover .g-content::before {
    transform: scale(0.9);
    box-shadow: -5px 10px 6px -8.5px #000, -1px 7px 16px -4px #000;
}
.g-resize::-webkit-resizer {
    background-color: transparent;
}

咱们经过上述的技巧,完成了一个只是运用 CSS 完成的自在拖拽的便签贴。咱们能够自在的将其拖拽到任意当地。看看作用:

超强的纯 CSS 鼠标点击拖拽作用

当然,咱们能够再合作上别的一个有意思是 HTML 特点 — contenteditable

contenteditable 是一个 HTML TAG 的特点,表明元素是否可被用户编辑。假如能够,浏览器会修正元素的部件以答应编辑。

简略修正一下 DOM 结构:

<div class="g-container">
    <div class="g-resize"></div>
    <div class="g-content" contenteditable="true"> Lorem ipsum dolor sit amet consectetur?</div>
</div>

此刻,元素不仅能够被拖动,甚至能够被重写,感受一下:

超强的纯 CSS 鼠标点击拖拽作用

纯 CSS 完成的作用,十分的有意思,完好的代码,你能够戳这儿:Pure CSS Auto Drag Demo

最后

基于 resize 这个 CSS 特点,其实还有许多有意思的用法。比如我之前运用了 Resize 完成了一个图片切换预览的功用:CSS 奇思妙想 | 运用 resize 完成强壮的图片拖拽切换预览功用 能够一并看看,相信能碰撞出更多火花。

感兴趣的同学能够自己着手,更多的去测验,组合。

好了,本文到此结束,希望本文对你有所协助 :)

假如还有什么疑问或者主张,能够多多沟通,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望奉告。