CSS魔法堂:Transition就这么好玩
前言
以前说起前端动画必须使用JS,而CSS3为我们带来transition和@keyframes,让我们可以以更简单(声明式代替命令式)和更高效的方式实现UI状态间的补间动画。本文为近期对Transition的学习总结,欢迎各位拍砖。
属性介绍
首先先我们简单粗暴了解transition属性吧!
transition: <transition-property> <transition-duration> <transition-timing-function> <transition-delay>;
/* 设置启用Transition效果的CSS属性
* 注意:仅会引发repaint或reflow的属性可启用Transition效果
* [CSS_animated_properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties)
*/
<transition-property>: all | none | <property> [,<property>]*
/* 设置过渡动画持续时间,单位为s或ms
*/
<transition-duration>: 0s | <time> [, <time>]*
/* 设置过渡动画的缓动函数
* cubic-bezier的值从0到1
* [一个很好用的cubic-bezier配置工具](http://cubic-bezier.com)
*/
<transition-timing-function>: linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n)
/* 设置过渡动画的延时,单位为s或ms
*/
<transition-delay>: 0s | <time> [, <time>]
另外我们可以一次性为多个CSS属性启动Transition效果
transition: width 1s ease .6s,
color .5s linear,
background 2s ease-in-out;
触发方式
既然Transition是UI状态间的补间动画,那么有且仅有修改UI状态时才能让动画动起来。那么就有3种方式了:
- 伪类.
:link,:visited,:hover,:active和:focus - 通过JS修改CSS属性值
- 通过JS修改className值
TransitionEnd事件详解
el.addEventListener("transitionend"
, e =>
{
const pseudoElement = e.pseudoElement // 触发动画的伪类
, propertyName = e.propertyName // 发生动画的CSS属性
, elapsedTime = e.elapsedTime // 动画的持续时间
// ..................
})
注意:每个启用TransitionCSS属性的分别对应独立的transitionend事件
/* 触发3个transitionend事件 */
transition: width 1s ease .6s,
color .5s linear,
background 2s ease-in-out;
Visibility也能transition?
在可启用Transition的CSS属性中,我们发现到一个很特别的CSS属性——visibility。visibility常与display相提并论的属性,它凭什么能启用Transition,而display不行呢?这个我真心不清楚,不过我们还是了解启用transition的visibility先吧!
visibility是离散值,0(hidden)表示隐藏,1(visible)表示完全显示,非0表示显示。那么visibility状态变化就存在两个方向的差异了:
- 从隐藏到显示,由于非0就是显示,那么从值从0到1的过程中,实际上是从隐藏直接切换到显示的状态,因此并没有所谓的变化过程;
- 从显示到隐藏,从1到0的过程中,存在一段时间保持在显示的状态,然后最后一瞬间切换到隐藏,因此效果上是变化延迟,依然没有变化过程。
上述表明启用transition的visibility并没有补间动画的视觉效果,那么到底有什么作用呢?答案就是不影响/辅助其他CSS属性的补间动画。其中最明显的例子就是辅助opacity属性实现隐藏显示的补间动画。
<style>
.form-input{
display: inline-flex;
line-height: 2;
border: solid 1px rgba(0,0,0,0.3);
}
.form-input:hover{
border: solid 1px rgba(0,0,0,0.4);
}
.form-addon{
font-style: normal;
color: #666;
background: #ddd;
padding-left: 10px;
padding-right: 10px;
border-right: solid 1px rgba(0,0,0,0.3);
}
.form-addon-after{
border-left: solid 1px rgba(0,0,0,0.3);
border-right: none 0;
}
.form-control{
border:none 0;
outline-color: transparent;
padding: 5px;
caret-color: #888;
font-size: 16px;
}
.tips-host{
position: relative;
}
.tips{
cursor: default;
z-index: 999;
position: absolute;
top: 120%;
font-size: 12px;
color: #444;
background: #ccc;
padding: .5em;
box-shadow: 2px 2px 10px #999;
transition: box-shadow .2s,
opacity 1s,
visibility .8s;
visibility: hidden;
opacity: 0;
}
.tips:hover{
box-shadow: 2px 2px 5px #999;
}
.tips::before{
content: "";
border: solid 10px transparent;
border-bottom: solid 10px #ccc;
position: absolute;
transform: translate(0, -100%);
}
.form-control:focus + .tips{
visibility: visible;
opacity: 1;
}
</style>
<div class="form-input tips-host" >
<i class="form-addon">Amount</i>
<input class="form-control">
<div class="tips">
Starts with alphabet, then anything you would like.
</div>
</div>

当opacity:0时,需要元素隐藏了但实际上它仍然位于原来的位置,而且可以拦截和响应鼠标事件,当出现元素重叠时则会导致底层元素失效。而由于visibility:hidden时,元素不显示且不拦截鼠标事件,所以在补间动画的最后设置visibility:hidden为不俗的解决办法。
display:none让transition失效的补救措施
虽然修改display有可能会引发reflow,但它依然不能启用Transition,这点真心要问问委员会了。更让人疑惑的是,它不单不支持启用Transition,而且当设置display:none时其余CSS属性的Transition均失效。难到这是让元素脱离渲染树的后果??
<style>
.box{
display: none;
background: red;
height: 20px;
}
</style>
<div class="box"></div>
<button id="btn1">Transition has no effect</button>
<button id="btn2">Transition takes effect</button>
<script>
const box = document.querySelector(".box")
, btn1 = document.querySelector("#btn1")
, btn2 = document.querySelector("#btn2")
btn1.addEventListener("click", e => {
box.style.display = "block"
box.style.background = "blue"
})
btn2.addEventListener("click", e => {
box.style.display = "block"
box.offsetWidth // 强制执行reflow
box.style.background = "blue"
})
</script>
上面的代码,当我们点击btn1时背景色的transition失效,而点击btn2则生效,关键区别就是通过box.offsetWidth强制执行reflow,让元素先加入渲染树进行渲染,然后再修改背景色执行repaint。
那么我们可以得到的补救措施就是——强制执行reflow,下面的操作均可强制执行reflow(注意:会影响性能哦!)
offsetWidth, offsetHeight, offsetTop, offsetLeft
scrollWidth, scrollHeight, scrollTop, scrollLeft
clientWidth, clientHeight, clientTop, clientLeft
getComputeStyle(), currentStyle()
总结
尊重原创,转载请注明转自:https://www.cnblogs.com/fsjohnhuang/p/9143035.html _肥仔John
参考
小tip: transition与visibility
https://www.cnblogs.com/surfaces/p/4324044.html
CSS魔法堂:Transition就这么好玩的更多相关文章
- CSS魔法堂:重拾Border之——更广阔的遐想
前言 当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...
- CSS魔法堂:display:none与visibility:hidden的恩怨情仇
前言 还记得面试时被问起"请说说display:none和visibility:hidden的区别"吗?是不是回答完display:none不占用原来的位置,而visibilit ...
- CSS魔法堂:更丰富的前端动效by CSS Animation
前言 在<CSS魔法堂:Transition就这么好玩>中我们了解到对于简单的补间动画,我们可以通过transition实现.那到底多简单的动画适合用transtion来实现呢?答案就是 ...
- CSS魔法堂:Box-Shadow没那么简单啦:)
前言 说起box-shadow那第一个想法当然就是用来实现阴影,其实它还能用于实现其他好玩的效果的,本篇就打算说说box-shadow的那些事. 二话不说看效果 3D小球 <style typ ...
- CSS魔法堂:重拾Border之——不仅仅是圆角
前言 当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...
- CSS魔法堂:重拾Border之——图片作边框
前言 当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...
- CSS魔法堂:重拾Border之——解构Border
前言 当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...
- CSS魔法堂:"那不是bug,是你不懂我!" by inline-block
前言 每当来个需要既要水平排版又要设置固定高宽时,我就会想起display:inline-block,还有为了支持IE5.5/6/7的hack*display:inline;*zoom:1;.然后发 ...
- CSS魔法堂:小结一下Box Model与Positioning Scheme
前言 对于Box Model和Positioning Scheme中3种定位模式的细节,已经通过以下几篇文章记录了我对其的理解和思考. <CSS魔法堂:重新认识Box Model.IFC.B ...
- CSS魔法堂:说说Float那个被埋没的志向
前言 定位系统中第一难理解就是Normal flow,而第二就非Float莫属了,而Float难理解的原因有俩,1. 一开头我们就用错了:2. 它跟Normal flow靠得太近了.本文尝试理清Fl ...
随机推荐
- angularjs 中通过 $location 进行路由跳转传参
$location.path('/page1').search({id: $scope.id,name:$scope.name}); 带参数跳转页面,在新的页面通过$routeParams接收参数 $ ...
- sparkSQL将谓词推入kudu引擎
kudu之所以执行非常快速,可以用来替代HDFS和Hbase等,一个主要原因是,我们可以将普通SQL中的谓词推入kudu引擎,这样kudu查询数据会变的非常快: 将谓词评估推入Kudu引擎可以提高性能 ...
- img 标签的 usemap 属性
<img src="1.gif" alt="Planets" usemap="#Map"/> <map name=&quo ...
- 函数对象的call()、apply() 方法区别
函数对象的call().apply() 方法 函数作为对象提供了call(),apply() 方法,他们也可以用来调用函数,这两个方法都接受一个对象作为参数,用来指定本次调用时函数中this的指向: ...
- BZOJ2084 [Poi2010]Antisymmetry Manachar
题目传送门 - BZOJ2084 题解 对于一个0我们把它看作01,1看作10,然后只要原串中的某个子串可以通过这两个变换成为回文串就可以满足条件了. 对于转换过的串,Manachar随便弄几下就可以 ...
- M. Subsequence 南昌邀请赛
链接: https://nanti.jisuanke.com/t/38232 先给出一个s母串 然后给出n个子串 判断是否为母串的子序列 3000ms 2993ms过的.... 蒻鲫的代码: 建立表 ...
- P1156 垃圾陷阱 DP
题目描述 卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中.“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2 \le D \le 100)D(2≤D≤100)英尺. 卡门 ...
- dp经典问题-最大连续子序列和 hdu1003
题目描述: 这道题我先后做过三遍,结果每一遍都没有做出来.今天再仔仔细细的研究了一下,才发现用动态规划更好理解. 关于求最大连续子序列和的博文转载如下:https://www.cnblogs.com/ ...
- Linux学习笔记8
其他常用命令 cd+回车=回车~ 进入当前用户主目录 查看指定进程信息 #ps -ef |grep 进程名 #ps ---查看属于自己的进程 #ps -aux 查看所有用户的执行进程 换成 p ...
- PHP foreach 循环
foreach (array_expression as $value) statementforeach (array_expression as $key => $value) ...