纯CSS实现height:0至auto过渡
组件封装时,很多时候需要折叠效果,子元素的高度无法确定,当高度从0变化到auto时不会触发transitions的过渡效果,本文将巧用grid布局解决这一问题。
问题描述
假设正在封装一个折叠面板组件,面板折叠使得默认高度为20px,而展开状态的高度应该由子元素决定,父元素高度由子元素决定,那么应该设置height为auto。但是这时将会出现一个问题,transitions过渡只支持固定高度值之间的变化,如20px -> 100px,并不支持高度至auto的变化,20px -> auto,我们的子元素高度是任意的,所以固定高度值的做法是不可取的。
html
<div class="demo">
<p>1</p>
<p>1</p>
<p>1</p>
</div>
20px -> 100px时:
css
.demo {
background: skyblue;
height: 20px;
overflow: hidden;
transition: height .5s;
}
.demo:hover {
height: 100px;
}
20px -> auto时:
css
.demo {
background: skyblue;
height: 20px;
overflow: hidden;
transition: height .5s;
}
.demo:hover {
height: auto;
}
解决方案
方法一:getComputedStyle(JS控制高度)
查看element等ui框架源码,可以发现折叠面板等实现大都使用了getComputedStyle API,通过JS获取子元素高度来实现过渡效果。但是我们很多时候都不希望样式与JS耦合,想要只用CSS来处理,这就有了方法二。
方法二:grid布局控制(纯CSS)
此方法需要增加一个父级display: grid
的元素,利用grid-template-rows
属性的0fr -> 1fr来控制高度的变化。
html
<div class="container">
<div class="demo">
<p>1</p>
<p>1</p>
<p>1</p>
</div>
</div>
css
.container {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows .5s;
}
.demo {
background: skyblue;
min-height: 20px;
overflow: hidden;
}
.container:hover {
grid-template-rows: 1fr;
}