你可能至少尝试过一次用 transition 从height: 0到auto的过渡... 结果发现根本不起作用!😖
让我们从一个例子讲起:
代码非常简单,如果你将鼠标悬停在手风琴上,它将会展开。看起来基本功能已经实现了,但是过渡效果看起来一点也不平滑。
但实际上 CSS 代码中已经加上了height的过渡:
.accordion-body {
height: 0;
transition: 500ms height ease;
}
.accordion:hover .accordion-body {
height: auto;
}
正如开篇说的那样:从height: 0到auto的过渡,根本没有任何过渡效果。
那怎样解决呢?🤔
方案一 (fixed height)
将 height 属性设置为一个固定的数字,而不是auto。
一定程度上这是可行的。但是这不是一个很好的方法:为了计算这个固定的数字,我们被迫使用 javascript 进行计算 dom clientHeight 实际有多么高。
显然这不是我们想要的方案。❎
那有没有一种仅使用 CSS 就可以实现过渡效果的解决方案呢?
方案二 (max-height)
我们可以用 maxheight来解决啊~😄
.accordion-body {
max-height: 0;
transition: 250ms max-height ease;
}
.accordion:hover .accordion-body {
max-height: 200px;
}
现在过渡效果可以正常平滑地过渡了。
唯一的小缺陷:由于为max-height定义了一个固定值,内容可能会溢出。
看起来只要max-height值合适,就可以了。
但是需要注意的是:max-height的值越高,过渡转换就越奇怪。 (不信你在CSS 代码中 把max-height改成 1000px 看看啥效果😁)
难道就没有更加优秀的方案嘛?使得我们一开始就能避开height、max-height
方案三 (CSS Grid)🎉
用 CSS Grid 创建单个网格项:grid-template-rows 使其从 0fr过渡到1fr。就是如此简单:
.accordion-body {
display: grid;
grid-template-rows: 0fr;
transition: 250ms grid-template-rows ease;
}
.accordion:hover .accordion-body {
grid-template-rows: 1fr;
}
.accordion-body-required-container {
overflow: hidden;
}
很简洁,没有花里胡哨的代码,也按照我们的预期 work 了。
此解决方案需要注意的一点:需要将 overflow: hidden 设置为 .accordion-body 的内部 div 才能使此工作。
原理:基于浏览器的新功能 grid-template-rows 跟踪动画,主流浏览器都支持。生产代码要使用这个特性,一定要先检查兼容性! 😉