Skip to content
On this page

纯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 -> 100px预览

20px -> auto时:

css
.demo {
  background: skyblue;
  height: 20px;
  overflow: hidden;
  transition: height .5s;
}

.demo:hover {
  height: auto;
}

20px -> 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;
}

grid方法效果预览

上次更新于: