如何使用css实现手风琴效果

背景

最近在公司做需求遇到一个很有趣很常见的需求也是实现一个类似手风琴的css效果,当鼠标移动上时,展开,扩展高度,当鼠标移开手,收缩,高度为0。

这里也分享给大家,我的实现思路和最终的解决方案。

如何实现手风琴效果

让我们从一个实际的例子开始。首先我们构建了一个简单的手风琴效果的菜单:

它的 HTML 代码非常简单:
我们先定义一个类名为 “accordion” 的 div 容器作为最外层的包裹,然后定义类名为 "accordion-title"的 div 容器作为标题容器,定义类名为"accordion-body"的div 容器作为内容容器

<div class="accordion">
  <div class="accordion-title">悬停我!</div>
  <div class="accordion-body">
    <div>
      <p>内容...</p>
    </div>
  </div>
</div>

我们希望实现的效果是当鼠标移上时,出现一个类似手风琴展开的效果,折叠时,类似手风琴收缩的效果,类似于“accordion-body”的高度平滑的从0过度到100。讲到这里,大家可能会立即想到,我们可以使用css的transition属性来实现平滑过渡的效果。我最开始也是一样的想法。给accordion-body加上transition: 500ms height ease;应该就能实现。

css代码:

.accordion-body {
  height: 0;
  transition: 500ms height ease;
}

.accordion:hover .accordion-body {
  height: auto;
}

jcode

❌ 但是经过实践,很明显,这种方法不起作用,CSS 不支持从 height: 0 过渡到 height: auto

那我们应该如何解决这个问题呢?

一种解决方案是我们可以将 height 属性设置为固定值,而不是 auto

虽然这样有效,但其实这不是一个特别好的方法:因为很多时候内容的具体高度是不固定的。

你可能会问?那我们还能使用纯 CSS 实现这个效果吗?

当然可以!我们可以使用 max-height代替 height 呢?

.accordion-body {
  max-height: 0;
  transition: 500ms max-height ease;
}

.accordion:hover .accordion-body {
  max-height: 200px;
}

jcode

由于我们给 max-height 定义了一个固定值,现在浏览器能够很好的地执行过渡动画了。

但是使用max-height产生的问题是,因为我们给 max-height 定义了一个固定值,当实际内容的高度比容器的高度高时就会产生溢出。
jcode

如果你能够确保你的内容永远不会超过容器的最大高度……那么这种方法已经可以完全满足了!

不过我们要注意的是,当max-height 的值越高,它的过渡效果就会呈现的越奇怪。

你可能会问,那我们有更好的选择吗?

我们可不可以从一开始就避免使用任何固定的高度/最大高度呢?

CSS Grid 可以解决这个问题!

我们可以使用一个巧妙的技巧来实现。

我们需要做的是让我们的 grid-template-rows0fr 过渡到 1fr:这样,我们的网格项目就能从 0 过渡到它的 “内容” 高度。

/* 设置手风琴内容部分的样式 */
.accordion-body {
  display: grid; /* 使用CSS网格布局 */
  grid-template-rows: 0fr; /* 设置网格行模板,0fr表示行的高度为0,内容不可见 */
  transition: 250ms grid-template-rows ease; /* 设置过渡效果,当行高度变化时,过渡时间为250毫秒,缓动函数为ease */
}

/* 当鼠标悬停在手风琴组件上时,改变手风琴内容部分的样式 */
.accordion:hover .accordion-body {
  grid-template-rows: 1fr; /* 设置网格行模板,1fr表示行的高度将占用可用空间,内容变为可见 */
}

/* 设置手风琴内容部分直接子元素的样式 */
.accordion-body > div {
  overflow: hidden; /* 设置内容溢出隐藏,这样当内容不可见时(高度为0),内容会被隐藏 */
}

jcode

我们需要注意的是,我们需要把.accordion-body 的内部 div 都设置为 overflow: hidden,他的效果才会生效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zayyo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值