前言

大家平时应该经常见到这种特效,很炫酷不是吗

这是谷歌Material Design中最常见的特效了,市面上也有很多现成的js库,用来模拟这一特效。但是往往要引入一大堆jscss,其实在已有的项目中,可能只是想加一个这样的按钮,来增强用户体验,这些js库就显得有些过于庞大了,同时由于是js实现,很多时候还要注意加载问题。

那么,有没有办法用css来实现这一特效呢?

思路

其实就是一个动画,一个正圆从小变大,用css3中的动画很容易实现

示例代码

@keyframes ripple{
from {
transform: scale(0);
opacity: 1;
}
to {
transform: scale(1);
opacity: 0;
}
}

通常用js来实现的方式很简单,就是给点击元素添加一个class,然后再动画结束后移除该class

示例代码

var btn = document.getElementById('btn');
btn.addeventlistener('click',function(){
addClass(btn,'animate')
},false)
btn.addeventlistener('transitionend',function(){//监听css3动画结束
removeClass(btn,'animate')
},false)

那么如何通过css来实现动画的触发呢?

CSS实现

css中与鼠标交互的伪类主要有

  • hover鼠标经过
  • :active鼠标按下
  • :focus鼠标聚焦
  • :checked鼠标选中

很多情况下,我们页面中的效果都是通过hover来实现的,鼠标放上去触发一个效果,离开还原,但是如果放上去马上离开,那么动画也会马上结束。

我们先试一下。

结构

这是我们写好的页面结构和样式

<style>
.btn{
display: block;
width: 300px;
outline: 0;
overflow: hidden;
position: relative;
transition: .3s;
cursor: pointer;
user-select: none;
height: 100px;
text-align: center;
line-height: 100px;
font-size: 50px;
background: tomato;
color: #fff;
border-radius: 10px;
}
</style>
<a class="btn">button</a>

很简单,就是一个普通的按钮样式

下面我们在按钮中添加我们需要的正圆。

我们用伪元素来实现

.btn:after{
content: '';
position: absolute;
width: 100%;
padding-top: 100%;
background: transparent;
border-radius: 50%;
left: 50%;
top: 50%;
transform: translate(-50%,-50%)
}

我们把上面的overflow: hidden去掉,把这个圆缩小一点看看效果

然后,我们写个缩放的动画

@keyframes ripple{
from {
transform:translate(-50%,-50%) scale(0);
/**由于我们默认写了变换属性,所以这里要补上translate(-50%,-50%),不然就会被替换了**/
background: rgba(0,0,0,.25);
}
to {
transform:translate(-50%,-50%) scale(1);
background: transparent;
}
}

hover小交互体验

鼠标经过试试?

.btn:hover:after{
animation: ripple 1s;
}

效果还是不错的,就是如果鼠标离开的太快,那么刚刚扩大的圆马上就缩回去了,有点违和

但是这不是我们想要的效果呀。我们希望的是点击一次触发一次,而不是这样放上去就完了,再也不会触发了。

active尝试

平时工作中,active用到的也比较多,通常是用在点击的效果上,那么拿来试试?

.btn:active:after{
animation: ripple 1s;
}

效果也是差强人意,有点类似鼠标按住的意思,你必须一直按住鼠标,才能完整的触发,比如说上面的例子,动画的运行实现是1s,那么你必须点在那个按钮上持续1s才能看到完整的动画效果,否则,就像上面鼠标离开一样,动画马上就缩回去了

focus体验

如果需要让任意一个元素获焦,你可以给太指定一个tabindex属性

<a class="btn" tabindex="1">button</a>
.btn:focus:after{
animation: ripple 1s;
}

foucs也可以触发,只是触发以后只有等失去焦点之后才能再次触发,实际的操作表现就是,点过一次以后,再点一下外面的空白

难道就没有办法了吗?

当然还是有的,放在最后的肯定就是解决方式,haha

checked

checked并不能直接触发,这是表单元素选中后触发的,为此,我们需要改造一下页面结构

<label class="btn">
<input type="checkbox"><span>button</span>
</label>

我们这里换成了lable并计入了input[type=checkbox]标签,主要是为了在点击按钮的时候触发input选中。

加一点样式

.btn>span:after{
/**换一下选择器**/
}
.btn>input[type=checkbox]{
display: none
}
.btn>input[type=checkbox]:checked+span:after{
animation: ripple 1s;
}

这样也能触发动画,但问题是,当再次点击的时候就成了非选中状态了,怎么触发动画呢?

其实可以用:not来实现

.btn>input[type=checkbox]:not(:checked)+span:after{
animation: ripple 1s;
}

乍一看好像挺聪明的,仔细一想,正反两个都写了动画,不就跟:checked没关系了?还不如直接

.btn>input[type=checkbox]+span:after{
animation: ripple 1s;
}

无限轮回中...

这个问题困扰了我好久,不过皇天不负有心人,后来试着在两种状态下触发不同的动画是可以分别触发的,如下

.btn>input[type=checkbox]:checked+span:after{
animation: ripple1 1s;
}
.btn>input[type=checkbox]:not(:checked)+span:after{
animation: ripple2 1s;
}

这个应该很好理解吧。

那么,重点来了,现在把动画ripple1ripple2里面的动画过程都改成一样,也是可以分别触发的,也就是说,只要动画名称不一样,css都会当成不同的动画来处理

这样就简单了,我们只需要默认一个状态,选中一个状态,然后分别触发名称不同的动画就行了~

.btn>input[type=checkbox]+span:after{
animation: ripple-in 1s;
}
.btn>input[type=checkbox]:checked+span:after{
animation: ripple-out 1s;
}
@keyframes ripple-in{
from {
transform:translate(-50%,-50%) scale(0);
background: rgba(0,0,0,.25);
}
to {
transform:translate(-50%,-50%) scale(1);
background: transparent;
}
}
@keyframes ripple-out{/*仅仅名称不同*/
from {
transform:translate(-50%,-50%) scale(0);
background: rgba(0,0,0,.25);
}
to {
transform:translate(-50%,-50%) scale(1);
background: transparent;
}
}

效果就如文章一开始所示,完美

完整demo如下

https://codepen.io/xboxyan/pe...

一些不足

由于上述动画样式在默认情况下就会被触发,所以页面加载进来就会看到按钮上的水滴动画运动一次,不过也不是特别明显,还可以接受。

其次,实际效果肯定是希望鼠标点击哪里,就以该点为中心扩散,我们css肯定是做不到这点的,只能从中心扩散,这也只能妥协了。这里提供一个思路,可以使用css的变量,每次点击的时候吧相应的值存在style里面,这样css中也能用上。

希望能用css今后挖掘出更多有趣的效果^ ^

喜欢的可以关注我的博客 https://blog.codelabo.cn

查看原文

纯css实现Material Design中的水滴动画按钮的更多相关文章

  1. [转]ANDROID L——Material Design详解(动画篇)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 转自:http://blog.csdn.net/a396901990/article/de ...

  2. [转]Android 5.0——Material Design详解(动画篇)

    Material Design:Google推出的一个全新的设计语言,它的特点就是拟物扁平化. Material Design包含了很多内容,今天跟大家分享一下Material新增的动画: 在Andr ...

  3. ANDROID L——Material Design具体解释(动画篇)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...

  4. 纯CSS实现帅气的SVG路径描边动画效果(转载)

    本文转载自: 纯CSS实现帅气的SVG路径描边动画效果

  5. 用纯CSS实现加载中动画效果

    HTML <div class="pswp__preloader__icn"> <div class="pswp__preloader__cut&quo ...

  6. 如何用纯 CSS 创作一个行驶中的火车 loader

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/RBLWzJ 可交互视频 ...

  7. 前端每日实战:91# 视频演示如何用纯 CSS 创作一个行驶中的火车 loader

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/RBLWzJ 可交互视频 此视频是可 ...

  8. 17.1拓展之纯 CSS 创作炫酷的同心圆旋转动画

    效果地址:https://codepen.io/flyingliao/pen/ebjEMm?editors=1100 HTML代码: <div class="loader"& ...

  9. 前端每日实战:119# 视频演示如何用纯 CSS 创作一个接扎啤的动画(内含2个视频)

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/rZeOQp 可交互视频 此视频是可 ...

随机推荐

  1. go net库

    1 使用Listen函数创建一个server ln, err := net.Listen("tcp", ":8080") if err != nil { // ...

  2. ESP32 Ethernet to wifi

    参考网址 https://github.com/espressif/esp-iot-solution/tree/master/examples/eth2wifi RMII PHY Wiring(RMI ...

  3. 给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回

    给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回 //统计字符串中出现的字符的出现次数 public function strNum(){ ...

  4. JavaScript的二维数组

    二维数组的初始化: 实例① var arr = [[1,2],['a','b']]; console.log(arr[1][0]); //a 第2列第1行所在的元素 实例② var arr = new ...

  5. Linux学习--第六天--软件包

    yum在线管理 管理的是rpm包,光盘里面都有 /etc/yum.repos.d下面有四个文件,对应网络yum源,光盘yum源等.如果需要用到哪个源,将其他三个源的enabled设置为0即可. |源配 ...

  6. fpga为什么要用nios 开发

    同一个项目可以用NIOS2也可以不用就可以完成,这句话说对也可以说不对,这要看是一个什么样的项目,你那样问的话可就说明有CPU和没CPU下的使用情况你还没有搞清楚,这两者并没有完全分开,简单的说就是有 ...

  7. Educational Codeforces Round 55 (Rated for Div. 2) D. Maximum Diameter Graph (构造图)

    D. Maximum Diameter Graph time limit per test2 seconds memory limit per test256 megabytes inputstand ...

  8. Codeforces 954 dijsktra 离散化矩阵快速幂DP 前缀和二分check

    A B C D 给你一个联通图 给定S,T 要求你加一条边使得ST的最短距离不会减少 问你有多少种方法 因为N<=1000 所以N^2枚举边数 迪杰斯特拉两次 求出Sdis 和 Tdis 如果d ...

  9. systemd 相关及服务启动失败原因

    1 查看启用的units systemctl list-unit-files | grep enabled 2 查看指定服务的日志 按服务单元过滤 journalctl -u j   查看j.serv ...

  10. php内置函数分析之current()、next()、prev()、reset()、end()

    current()初始指向插入到数组中的第一个单元 next() 将数组的内部指针向前移动一位 prev() 将数组的内部指针倒回一位 reset() 将数组的内部指针指向第一个单元 end() 将数 ...