css不能在display:none和display:block之间进行动画,并且也不能在height:0和height:auto之间进行动画。这里我研究了一下在display:none和display:block之间进行动画的解决方案,记录下来供以后开发时参考,相信对其他人也有用。
我的理解是这样的:由于display:none会引起页面的重绘事件,所以它是一个异步的延时事件,所以浏览器其实会先解析animate的代码,然后再执行display:none。
这样就引发了一个问题:如果我们要设置类似淡入淡出的效果怎么办?就是让元素在消失/出现的同时产生动画怎么办?这里我研究了2个解决方案。
不利用display:none,而是利用它的替代方式:
</>code
- opacity: 0;visibility: hidden;
但是这样会占据空间。如果不想占据空间的话,只能使用绝对定位,把元素独立出去。这个时候会有一个层叠问题,所以需要搭配z-index控制层叠关系使它出现或者消失。
示例如下:
</>code
- //自身css效果
- .animate {
- position: absolute;
- top: 0;
- left: 0;
- transition: 1s;
- opacity: 0;
- visibility: hidden;
- z-index: 0;
- }
- //出现时的效果
- .cur {
- opacity: 1;
- visibility: visible;
- z-index: 10;
- }
jquery里面也有淡入淡出的方法,它是怎么实现的呢?通过查资料可以知道,它是通过deferred对象通过延时display: none来实现的。好处是能够适用于出现时占据空间,消失时又不占据空间的情况。实例如下:
</>code
- //css
- .div {
- display: none;
- }
- .div-animate1 {
- display: block;
- visibility: hidden;
- opacity: 0;
- transform: translate3d(100px, 0, 0);
- transition: 1s;
- }
- .div-animate2 {
- visibility: visible;
- opacity: 1;
- transform: translate3d(0, 0, 0);
- }
- //js
- function divAnimate1($div, divClass1, divClass2) {
- $div.addClass(divClass1);
- setTimeout(function(){
- $div.addClass(divClass2);
- });
- }
- function divAnimate2($div, divClass1, divClass2) {
- $div.removeClass(divClass2);
- setTimeout(function(){
- $div.removeClass(divClass1);
- }, 1000); //1s是动画时间。
- }
我还试过用transitionend事件,window.requestanimationframe来实现,但是都或多或少的有副作用。
另外总结一下:
如果消失前后都需要占据空间,则用visiblity。
如果消失前后都不需要占据空间,则用绝对定位和visiblity。
如果消失前需要占据空间但是消失后不需要占据空间,则用timeout和visiblity。
DISPLAY:NONE的元素如何触发过渡动画?
display:none的元素更改为display:block为何不可以和其他属性修改一样触发动画呢?
这是因为display属性刚开始是none,所以还没有创建,改为block之后需要等待js渲染队列更新
但是transition属性在一开始就有了,所以transform改变元素的时候并没有触发动画
解决方法:让元素获取dom.offsetHeight,触发js渲染队列更新,让元素先展示出来。
</>code
- <!DOCTYPE html>
- <html>
- <head>
- <title>测试</title>
- <style type="text/css">
- html, body, div, span,
- h1, h2, h3, h4, h5, h6, p
- a, img, ol, ul, li
- {
- margin:0;padding:0;border:0;outline:0;
- }
- ul, li{
- list-style-type: none;
- }
- .father{
- border: 1px solid black;
- height: 300px;
- width: 1000px;
- }
- .one{
- background-color: red;
- height: 300px;
- width: 200px;
- display: none;
- transition: 1s ease;
- }
- </style>
- </head>
- <body>
- <div class="father">
- <div class="one"></div>
- <button type="button" onclick="change()">测试</button>
- </div>
- <script>
- function change(){
- var one = document.getElementsByClassName('one')[0];
- one.style.display='block';
- // 区别在于有没有获取one.offsetHeight
- console.log(one.offsetHeight);
- one.style.transform='translateX(200px)';
- }
- </script>
- </body>
- </html>
用opacity实现淡入淡出的效果。噢!good!一切正常
</>code
- <!DOCTYPE html>
- <html>
- <meta charset="uft-8">
- <head>
- <style>
- .div1{
- background: red;
- }
- .div2 {
- width:100px;
- height:100px;
- background:blue;
- transition:opacity 2s;
- -moz-transition:opacity 2s; /* Firefox 4 */
- -webkit-transition:opacity 2s; /* Safari and Chrome */
- -o-transition:opacity 2s; /* Opera */
- opacity: 0;
- }
- .div1:hover .div2 {
- opacity:1;
- }
- </style>
- </head>
- <body>
- <div class="div1">
- <p>请移动到红色div上</p>
- <div class="div2"></div>
- </div>
- </body>
- </html>
或者用animation,在keyframe中写也一样。这里就不写出代码了
但是难免我们会遇到这样的需求,也一定会遇到: 我们都知道opacity:0的时候,其实他还是占页面空间的,他会遮挡到他下面的层(不是视觉上)。而且绑定在他上面的一些onclick事件之类的,也同样会发生。 这时候我们想在opacity:0的时候,把他隐藏掉,用display: none。 好,那我们稍微在css中加几句,变成
</>code
- .div1{
- background: red;
- }
- .div2 {
- width:100px;
- height:100px;
- background:blue;
- transition:opacity 2s;
- -moz-transition:opacity 2s; /* Firefox 4 */
- -webkit-transition:opacity 2s; /* Safari and Chrome */
- -o-transition:opacity 2s; /* Opera */
- opacity: 0;
- display: none;
- }
- .div1:hover .div2 {
- opacity:1;
- display:block
- }
打开浏览器看一下效果先。 我擦。。。。淡入淡出的效果全没了怎么回事。。。这简直是破坏性的作用,这也是之前做动画过程中遇到的大坑
聪明的码农们当然有办法来解决这种情况。 大家都知道visibility的效果其实跟 display 在一定程度上相似, 当然是一定程度上。 那为什么说只是一定程度上相似呢,因为它仍然是占空间的,那么这时候看官一定会说,这么用跟opacity压根没区别呀
但聪明的码农们一定又想到,这时候,他是不会遮挡到下面的层的,也就是说 他跟opacity这样的存在不同,onclick等事件是不会发生的。
我们来说下visibility, 常用到的是visible和 hidden 两个值。但也可以是数值, 等于0时相当于hidden,而只要大于0时,visibility就为visible。那我们利用这点。
</>code
- .div1{
- background: red;
- }
- .div2 {
- width:100px;
- height:100px;
- background:blue;
- transition:all 2s;
- -moz-transition:all 2s; /* Firefox 4 */
- -webkit-transition:all 2s; /* Safari and Chrome */
- -o-transition:all 2s; /* Opera */
- visibility: hidden
- }
- .div1:hover .div2 {
- visibility: visible
- }
浏览一下,会发现,这时候是会有延时隐藏的效果的。很好,又发现新东西了
那渐变的效果怎么办。。。。
聪明的码农们又想起了opacity 。。。结合起来用会怎么用呢
</>code
- .div1{
- background: red;
- }
- .div2 {
- width:100px;
- height:100px;
- background:blue;
- transition:all 2s;
- -moz-transition:all 2s; /* Firefox 4 */
- -webkit-transition:all 2s; /* Safari and Chrome */
- -o-transition:all 2s; /* Opera */
- visibility: hidden;
- opacity: 0
- }
- .div1:hover .div2 {
- visibility: visible;
- opacity: 1
- }
浏览下先。。。。!!!!一切正常了
其实,visibility会在opacity生效后再应用。比如隐藏时,先opacity变为0,再应用了visibility:hidden 这时候就隐藏起来了,相关的事件也不会发生。 看来display:none这时候被抛弃了啊
当然,有人会说visibility:hidden始终是占着页面空间的,display能够减少页面的repaint,还是要用display:none怎么做呢
聪明的码农又想到了: 先把display变成block 然后延迟transition动画的执行
当然啦 这就需要用到JS了
以上就是css3 动画与display:none冲突的解决方法!
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛