對於未知高度的盒子,如何實現展開收起的transition過渡效果

我們經常碰到一種情況,點擊某個按鈕需要對某個盒子的內容進行展開收起,很多時候我們會用display:none | block;實現其內容的出現和消失。但這個辦法做出來的視覺效果很生硬,這時候我們就想用transition做過渡動畫的緩沖效果,達到優化視覺體驗的目的。
不過,由於盒子高度是由內容撐起的,我們也不知道height最終會是多少,而transition對於height從0-auto,從0-100%經常是不起作用的。所以直接這么用,一般以失敗告終。
下面是我針對這一場景的解決辦法。中心思想就是:讓父元素的height屬性進行transition過渡,只有一個子元素用來存放展開內容,展開時將子元素的height賦值給父元素。
HTML代碼:
<p>
開合動畫開關按鈕:
<i
className={`icon ${this.isShowContent ? "open" : ""}`}
onClick={this.showContent}
>
>
</i>
</p>
<div className="transition-wrapper">
<div className="content transition-content">
我是內容,我是內容,我是內容,我是內容,我是內容,
我是內容,我是內容,我是內容,我是內容,我是內容,
我是內容,我是內容,我是內容,我是內容,我是內容,
我是內容,我是內容,我是內容,我是內容,我是內容,
我是內容,我是內容,我是內容,我是內容,我是內容,
我是內容,我是內容,我是內容,我是內容,我是內容,
我是內容,我是內容,我是內容,我是內容,我是內容,
我是內容,我是內容,我是內容,我是內容,我是內容,
</div>
</div>
JS代碼:
// 對於未知高度盒子的展開合並動畫
showContent = () => {
this.setState({ isShowContent: !this.isShowContent });
this.isShowContent = !this.isShowContent;
const wrapper = document.querySelector(".transition-wrapper");
if (this.isShowContent) {
/*
因為子元素只是被父元素(height:0px;overflow:hidden)隱藏起來了,
所以它的高是真實的(由內容撐起),因此我們可以獲得子元素的高,
並將它賦值給父元素,使父元素擁有內容展開后的高。
以此達到觸發transition過渡動畫的目的。
*/
const content = document.querySelector(".transition-content");
const height = content.offsetHeight;
wrapper.style.height = height + "px";
} else {
wrapper.style.height = 0;
}
};
CSS代碼:
.icon {
padding: 5px 10px;
width: fit-content;
height: fit-content;
display: inline-block;
background-color: rgba(34, 2, 77, 0.5);
color: #fff;
text-align: center;
transform: rotate(0);
cursor: pointer;
}
.icon.open {
transform: rotate(90deg);
}
.transition-wrapper {
border: 1px solid #000;
width: fit-content;
height: 0px;
overflow: hidden;
transition: height 0.5s ease;
.content {
background-color: aqua;
border: 5px white solid;
width: 300px;
}
}