Blog Logo

30 May 2023 ~ 4 min read

从高度0过渡到自动高度的两个方式


你尝试做一个collapses, 想着用css完成这个折叠动画效果.

这个效果很简单,鼠标hover一个button 下方的content就展示出来 做一个简单的高度transition

它可以很好地打开和关闭, 但不会产生动画.
咦? 怎么回事, transition没用了?
在这个情况下, 你可能想到用js去实现这个效果,写一个类似于缓动动画去增加(打开时)和减少(关闭时)height.


然而, 我了解到两种不同的方法来解决这个问题, 不需要 JavaScript 的帮助. 只需要对其父元素的一些设置即可


使用flex

.wrapper {
  display: flex;
}

.content {
  max-height: 0;
  overflow: hidden;
  transition: all 0.5s ease-out;
}

button:hover + .content {
  max-height: 100%;
}

在content上加上一个wrapper元素, 然后不要忘了在content和wrapper中间再加上一个额外的div即可


<button>hover开启content</button>
<div class="wrapper">
<div>
    <div class="content">
    <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
    <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
    <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
    </div>
</div>
</div>

这种方法的缺点是虽然内部元素动画很平滑, 但其容器却不然, 会立即伸缩到位. 但在某些情况下这可能更可取, 因为浏览器不需要不断地重排其下方页面的所有内容, 对性能更友好.


使用grid

这个有点简单, 可能也更容易理解.
使用单个网格项创建 CSS 网格.
你所要做的就是将 grid-template-rows 从 0fr 过渡到 1fr, 以便网格项过渡到其自动高度:

.wrapper {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s ease-out;
}

.button:hover + .wrapper {
  grid-template-rows: 1fr;
}

.container {
  overflow: hidden;
}

而且并不需要额外的一个div将container包住


<button>hover开启content</button>
  <div class="wrapper">
    <div class="content">
      <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
      <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
      <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
      <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
      <p>这是一段内容,并没有任何意义,你为什么要看完我</p>
    </div>
  </div>


这种方法感觉干净很多. 只需两个 DOM 节点, 下面的所有页面内容都会像你期望的那样流畅地执行动画效果.

警告:

你不能向content添加任何padding. 如果需要添加padding, 则必须在content元素内再添加一个额外元素, 并padding设置在其上.


Hi, I'm Jesse. I'm a frontend developer in Shenzhen. see some of my work on GitHub,