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沖突的解決方法!
如對本文有疑問,請提交到交流論壇,廣大熱心網友會為你解答??! 點擊進入論壇