实现高度的过渡效果

前言

在实现鼠标移入某个元素,展开某个列表的功能时,可能列表的长度是不固定的,就无法通过写死高度去实现过渡效果。

公共样式

html 复制代码
<div class="button">
  <div class="text">Hover me</div>
  <div class="list">
    <div class="content">
      Change, a constant and inevitable force in our lives, often brings a mix
      of excitement, fear, and uncertainty. It's the engine of progress,
      pushing us out of our comfort zones and into new territories. While it
      can be daunting, embracing change can lead to personal growth and new
      opportunities.
    </div>
  </div>
</div>
css 复制代码
.button {
  padding: 10px;
  width: fit-content;
  background: aquamarine;
  border-radius: 10px;
}

 .button:hover .list {
   visibility: visible;
}

 .list {
   position: absolute;
   visibility: hidden;
   width: 200px;
   background: antiquewhite;
   border-radius: 10px;
}

尝试 height: auto

那如果 hover 后把列表的高度改为 auto 呢,代码如下:

css 复制代码
 .button:hover .list {
   height: auto;
}

 .list {
   overflow: hidden;
   height: 0;
   transition: 0.3s;
}

实现效果:

可以看到没出现过渡效果,这是因为过渡 transition 只对于属性值是数值的才有效,显然 auto 并不是数值类型。

尝试 max-height

height 改为 max-height

css 复制代码
.button:hover .list {
  max-height: 800px;
}

.list {
  overflow: hidden;
  max-height: 0;
  transition: 0.3s;
}

过渡的效果和预想的不太一样,速度有点快。因为过渡是按照设置的 800px 去计算的。

尝试 transform: scale()

css 复制代码
.button:hover .list {
  transform: scaleY(1);
}

.list {
  overflow: hidden;
  transform: scaleY(0);
  transform-origin: top;
  transition: 0.3s;
}

可以看到里面的内容也被压缩了,效果不太好。

尝试 grid 布局

css 复制代码
.button:hover .list {
  grid-template-rows: 1fr;
}

.list {
  display: grid;
  grid-template-rows: 0fr;
  transition: 0.3s;
}

.list .content {
  overflow: hidden;
}

使用grid可以完美的实现想要的效果,虽然主流的浏览器都已经支持,但在实际使用中还是要注意下兼容性问题。

使用 js

js 复制代码
const button = document.querySelector(".button");
const list = document.querySelector(".list");

button.addEventListener("mouseover", () => {
  list.style.height = "auto";
  const height = list.clientHeight;
  list.style.transition = "0.3s";
  list.style.height = 0;
  list.clientHeight; // 强制回流,让 list 高度变为 0
  list.style.height = `${height}px`;
});
button.addEventListener("mouseout", () => {
  list.style.height = 0;
});

实现原理: FLIP

实现思路:

  1. 鼠标移入按钮时,先把list的高度改为auto,让其自动计算高度。
  2. 记录计算出的高度,这里使用了clientHeight会使浏览器回流,虽然此时浏览器还没有重绘,但可以获取到listheightauto时的高度。
  3. 加入过渡效果,这里可以写在css里。设置list高度为0
  4. 读取listclientHeight使浏览器回流,让list的实际高度为0
  5. 设置list的高度为之前记录的值。
相关推荐
GreenTea27 分钟前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
killerbasd2 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
吴声子夜歌2 小时前
ES6——二进制数组详解
前端·ecmascript·es6
码事漫谈3 小时前
手把手带你部署本地模型,让你Token自由(小白专属)
前端·后端
ZC跨境爬虫3 小时前
【爬虫实战对比】Requests vs Scrapy 笔趣阁小说爬虫,从单线程到高效并发的全方位升级
前端·爬虫·scrapy·html
爱上好庆祝3 小时前
svg图片
前端·css·学习·html·css3
王夏奇3 小时前
python中的__all__ 具体用法
java·前端·python
大家的林语冰4 小时前
《前端周刊》尤大开源 Vite+ 全家桶,前端工业革命启动;尤大爆料 Void 云服务新产品,Vite 进军全栈开发;ECMA 源码映射规范......
前端·javascript·vue.js
jiayong234 小时前
第 8 课:开始引入组合式函数
前端·javascript·学习
田八4 小时前
聊聊AI的发展史,AI的爆发并不是偶然
前端·人工智能·程序员