概述
css不能在display:none和display:block之間進行動畫,並且也不能在height:0和height:auto之間進行動畫。這里我研究了一下在display:none和display:block之間進行動畫的解決方案,記錄下來供以后開發時參考,相信對其他人也有用。
參考資料:
CSS3 Animation and Display None
解決transition動畫與display沖突的幾種方法
機制
我的理解是這樣的:由於display:none會引起頁面的重繪事件,所以它是一個異步的延時事件,所以瀏覽器其實會先解析animate的代碼,然后再執行display:none。
這樣就引發了一個問題:如果我們要設置類似淡入淡出的效果怎么辦?就是讓元素在消失/出現的同時產生動畫怎么辦?這里我研究了2個解決方案。
利用絕對定位和visiblity
不利用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;
}
利用timeout
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。