css不能在display:none和display:block之间进行动画,并且也不能在height:0和height:auto之间进行动画。这里我研究了一下在display:none和display:block之间进行动画的解决方案,记录下来供以后开发时参考,相信对其他人也有用。
我的理解是这样的:由于display:none会引起页面的重绘事件,所以它是一个异步的延时事件,所以浏览器其实会先解析animate的代码,然后再执行display:none。
这样就引发了一个问题:如果我们要设置类似淡入淡出的效果怎么办?就是让元素在消失/出现的同时产生动画怎么办?这里我研究了2个解决方案。
不利用display:none,而是利用它的替代方式:
opacity: 0;visibility: hidden;
但是这样会占据空间。如果不想占据空间的话,只能使用绝对定位,把元素独立出去。这个时候会有一个层叠问题,所以需要搭配z-index控制层叠关系使它出现或者消失。
示例如下:
//自身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来实现的。好处是能够适用于出现时占据空间,消失时又不占据空间的情况。实例如下:
//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渲染队列更新,让元素先展示出来。
<!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!一切正常
<!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中加几句,变成
.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。那我们利用这点。
.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 。。。结合起来用会怎么用呢
.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冲突的解决方法!
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛