likes
comments
collection
share

使用纯CSS给不定高度的容器添加过渡效果-flex与grid还在为高度过渡效果苦恼吗?快来瞧瞧吧,今天叫你两种新方式,保

作者站长头像
站长
· 阅读数 20

写在开头

哈喽,各位UU早上好呀!😋

最近,小编忙于整理一些前端的知识点,不停感叹前端的体系真是越来越庞大了,太多也太杂,有点头大。😵

而且呢,俺发现在这些体系下,还存在很多令人抓狂的词汇缩写,如下:

使用纯CSS给不定高度的容器添加过渡效果-flex与grid还在为高度过渡效果苦恼吗?快来瞧瞧吧,今天叫你两种新方式,保

这些还只是很小很小一部分,随手想到就写,还有太多太多。😐

真是太难了,这年头,不卷不行!

算了,回到正题!这次要分享的是关于高度过渡效果的内容,具体效果如下,请诸君按需食用。

使用纯CSS给不定高度的容器添加过渡效果-flex与grid还在为高度过渡效果苦恼吗?快来瞧瞧吧,今天叫你两种新方式,保

问题

今天,在Coding中寻思着给新做的下拉菜单增添一点"魔法"🌈——也就是给它展开和收起加上个高度过渡效果,让操作体验更好些。

Em...😐这不是手到擒来的事嘛,开整:

<!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        padding: 20vh;
        margin: 0;
        height: 100vh;
        display: flex;
        align-items: center;
        flex-direction: column;
      }
      .dropdown {
        height: 0;
        transition: height 2s linear;
        overflow: hidden;
        color: #fff;
        background-color: #5468ff;
      }
      .dropdown > div {
        height: 34px;
        line-height: 34px;
        padding: 0 10px;
      }
      .container:has(.btn:hover) .dropdown {
        height: auto;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <button class="btn">Hover me!</button>
      <div class="dropdown">
        <div>苹果~</div>
        <div>香蕉~</div>
        <div>水蜜桃~</div>
        <div>橙子~</div>
        <div>葡萄~</div>
      </div>
    </div>
  </body>
</html>

效果:

使用纯CSS给不定高度的容器添加过渡效果-flex与grid还在为高度过渡效果苦恼吗?快来瞧瞧吧,今天叫你两种新方式,保

呃...效果有点差强人意,根本没用!

天真了🙊,以为让高度(height)从0auto过渡就能搞定!结果却不行。❌

CSS 中,如果我们尝试将 height0过渡到auto ,那么它将不起作用,会发生的情况是元素将直接捕捉到 height:auto 状态而不进行过渡。

分析与方案

其实这个问题背后真正的原因是:回流

回流与重绘相信前端小伙伴都有所了解的,懂得都懂啦。😋

  • 回流:回流也称重排,当DOM进行一些位置和大小(几何信息)的变化时,浏览器需要重新计算元素的信息,再将其重新放置或绘制在正确的位置上,这个过程就叫做回流。

  • 重绘:当一个元素外观发生变化,但是没有改变元素的布局,只需要重新把元素的外观绘制出来,这个过程就叫做重绘。

有时候,咱们可能只是轻轻一挥手,改了某一个元素的样式,却意外地触发了浏览器的大动作——它得重新绘制整个页面的大工程,这个过程可是相当耗资源的!

呃...反正呢,要知道回流是一项成本非常高的操作。

而现在如果浏览器能处理从0转换为auto的过程,则浏览器必须对动画的每一步执行重排以确定其他元素的位置,记住,是每一帧都要进行重排哦!但由于缺少起始值和结束值,这一过程无法被优化,从而可能拖累性能。

所以,结论:height0过渡到auto的过程无法被浏览器所处理。🙈


不过,山重水复疑无路,柳暗花明又一村。东路不通,就走西路呗,现在已经有一些其他方案来解决这个问题:

  • 最大高度猜测大法:我们可以给容器设定一个足够大的最大高度,然后过渡到0。但缺点是,如果预估的高度过大,过渡动画就会变得漫长,影响用户体验。

  • 缩放(scale)大法:从scale(0)动画过渡到scale(1),虽然这个方法不会引起回流,但内容的扭曲可能会让动画看起来不太自然。

  • JS 魔法大法:通过JavaScript动态获取内容高度,这无疑是最佳方案,但需要额外的时间和代码来实现。

😪 就这?

当然不是,这些都有一定的弊端!

下面,来介绍两种更为优雅的方法,纯CSS噢😉,它们可以在不损害动画美观和浏览器性能的前提下,实现从0auto的高度过渡。

方案一:flex

flex 布局相信也都知道,在该布局下,其最大高度(max-height)的行为有所不同。在弹性布局中,最大高度的值将始终是弹性布局的高度,这是一个结论❗

但是,咱们需要一个额外的 div 才能完成,Em......。🙊

先直接来看吧,如下:

<!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        padding: 20vh;
        margin: 0;
        height: 100vh;
        display: flex;
        align-items: center;
        flex-direction: column;
      }
      .dropdown {
        transition: all 0.3s ease;
        overflow: hidden;
        color: #fff;
        background-color: #5468ff;
        /* 通过max-height来过渡 */
        max-height: 0;
      }
      .dropdown > div {
        height: 34px;
        line-height: 34px;
        padding: 0 10px;
      }
      .container:has(.btn:hover) .dropdown {
        /* 通过max-height来过渡 */
        max-height: 100%;
      }
      /* 使用flex布局 */
      .dropdown-box {
        display: flex;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <button class="btn">Hover me!</button>
      <div class="dropdown-box">
        <!-- 额外必须的div -->
        <div>
          <div class="dropdown">
            <div>苹果~</div>
            <div>香蕉~</div>
            <div>水蜜桃~</div>
            <div>橙子~</div>
            <div>葡萄~</div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

效果:

使用纯CSS给不定高度的容器添加过渡效果-flex与grid还在为高度过渡效果苦恼吗?快来瞧瞧吧,今天叫你两种新方式,保

还可以吧,效果上看是能满足的。唯一缺陷就是多一个额外 div 的存在,有点会膈应。😶

方案二:grid(fr)

方案二需要使用到网格布局——grid,而且它还用上了表达比例关系的 fr 单位。

实现如下:

<!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        padding: 20vh;
        margin: 0;
        height: 100vh;
        display: flex;
        align-items: center;
        flex-direction: column;
      }
      .dropdown {
        overflow: hidden;
        color: #fff;
        background-color: #5468ff;
      }
      .dropdown > div {
        height: 34px;
        line-height: 34px;
        padding: 0 10px;
      }
      .container:has(.btn:hover) .dropdown-box {
        grid-template-rows: 1fr;
      }
      .dropdown-box {
        display: grid;
        grid-template-rows: 0fr;
        transition: grid-template-rows 0.5s ease-out;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <button class="btn">Hover me!</button>
      <div class="dropdown-box">
        <div class="dropdown">
          <div>苹果~</div>
          <div>香蕉~</div>
          <div>水蜜桃~</div>
          <div>橙子~</div>
          <div>葡萄~</div>
        </div>
      </div>
    </div>
  </body>
</html>

效果:

使用纯CSS给不定高度的容器添加过渡效果-flex与grid还在为高度过渡效果苦恼吗?快来瞧瞧吧,今天叫你两种新方式,保

又有了一定的改进吧,也不需要额外的 div 元素的协同了,这就挺好。😃


至此,本篇文章就写完啦,撒花撒花。

使用纯CSS给不定高度的容器添加过渡效果-flex与grid还在为高度过渡效果苦恼吗?快来瞧瞧吧,今天叫你两种新方式,保

转载自:https://juejin.cn/post/7403426280941666304
评论
请登录