【日常记录】【CSS】css 和 js 实现高度的动画效果,常用于下拉菜单,下拉选项要做动画处理

0. 引言

在 下拉菜单的时候,很常见 鼠标移入,下面的下拉项 缓慢的出来,一个动画效果
还有 elementUI的选择器组件等其他组件

1. 界面结构搭建

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    .item_title {
      color: #fff;
      background-color: #409eff;
      border-color: #409eff;
      border-radius: 5px;
      ;
      padding: 5px;
      text-align: center;
      cursor: pointer;
    }

    .dropdown-menu {
      margin-top: 5px;

      background-color: #409eff;
    }

    .container {
      margin: auto;
      width: 100px;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="item">
      <div class="item_title">下拉菜单</div>
      <div class="dropdown-menu">
        <div class="dropdown-item">1</div>
        <div class="dropdown-item">2</div>
        <div class="dropdown-item">3</div>
      </div>
    </div>
  </div>

</body>

</html>

在这里插入图片描述

2. 第一种方式:使用 height

最常见的方法是,先让下拉菜单的 盒子 高度变成 0,然后添加 overflow:hidden ,让溢出的元素隐藏,当鼠标移入 下拉菜单这个按钮的时候,把高度变成固定值

在这里插入图片描述

    .dropdown-menu {
      margin-top: 5px;

      background-color: #409eff;

      height: 0px;
      overflow: hidden;
      transition: all .5s;
    }

    .item:hover .dropdown-menu {
      height: 100px;
    }

但这个方法有一个弊端,有时候高度并不能直接确定,谁也不知道里面的内容有多少东西!

那假设,我们把这个 height 属性的值,换成 auto 它就不能实现动画了
因为这个高度是不确定的,浏览器无法对不确定的高度实现动画

    .item:hover .dropdown-menu {
      height: auto;
    }

在这里插入图片描述

3. 第二种方式:使用 max-height

可以给 max-height 做动画,只要保证你的内容不会超过这个数就可以

    .dropdown-menu {
      margin-top: 5px;

      background-color: #409eff;

      max-height: 0px;
      overflow: hidden;
      transition: all 1s;
    }

    .item:hover .dropdown-menu {
      max-height: 1000px;
    }

这个地方,会导入,

  • 鼠标移入的时候,会感觉 很快
  • 鼠标移出的时候,会感觉有点卡

因为,鼠标移入的时候,动画过程实际上是 0px => 1000px 又加上移出隐藏了,所以会感觉很快

因为,鼠标移出的时候,动画过程实际上是 1000px => 0px 又加上溢出隐藏了,所以会感觉有一点卡顿

在这里插入图片描述

4. 第三种方式:使用 transform

可以使用 transform 的 scaleY ,让它从Y轴 上本来是 0 ,然后到 1 变化

在这里插入图片描述

但这个地方,会发现有点奇怪,这个地方,是因为 默认的变换原点就是 DOM 元素的中心垂直水平居中的点
可以通过 transform-origin: top center; 修改,把 变换原点改成 垂直方向的顶部,水平方向的中心

在这里插入图片描述
在这里插入图片描述

5. 第五种方式:使用JS

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    .item_title {
      color: #fff;
      background-color: #409eff;
      border-color: #409eff;
      border-radius: 5px;
      padding: 5px;
      text-align: center;
      cursor: pointer;
    }

    .dropdown-menu {
      margin-top: 5px;

      background-color: #409eff;
      height: 0;
      overflow: hidden;
    }

    .container {
      margin: auto;
      width: 100px;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="item">
      <div class="item_title">下拉菜单</div>
      <div class="dropdown-menu">
        <div class="dropdown-item">1</div>
        <div class="dropdown-item">2</div>
        <div class="dropdown-item">3</div>
      </div>
    </div>
  </div>
  <script>
    let itemTitleEl = document.querySelector('.item_title')
    let dropdownMenuEl = document.querySelector('.dropdown-menu')
    itemTitleEl.addEventListener("mouseenter", function () {
      dropdownMenuEl.style.height = 'auto'

      const { height } = dropdownMenuEl.getBoundingClientRect()
      dropdownMenuEl.style.height = 0
      console.log("mousenter", height)


      dropdownMenuEl.style.transition = 'all 1s'
      dropdownMenuEl.style.height = height + 'px'
    })
    itemTitleEl.addEventListener("mouseleave", function () {
      dropdownMenuEl.style.height = 0
    })
  </script>
</body>

</html>

这个实现思路就是:

  1. 监听鼠标移入下拉菜单按钮(document.querySelector('.item_title'))事件
  2. 鼠标移入后,把下拉菜单(document.querySelector('.dropdown-menu')) height 换成 auto ,目的是为了拿到这个下拉菜单DOM的高度
  3. 使用 DOM.getBoundingClientRect() ,拿到这个下拉菜单DOM的高度
  4. 下拉菜单高度设置成 拿到的实际值
  5. 下拉菜单 添加 transition
  6. 鼠标移出,高度变成 0

在这里插入图片描述

可以看到鼠标移入以后是 直接闪一下的,根本没有做动画,这个原因是因为:先设置了 高度是 auto,然后设置高度为 0 ,然后又设置高度为 具体值,,,修改高度,会触发 回流(Layout)

但是浏览器为了避免,连续多次操作导致布局树反复计算,浏览器会合并这些操作,当JS代码全部完成后在进行统一计算,所以,回流 这个操作,导致 布局树发生计算是异步

所以如若想让它立即执行 回流,则需要 获取布局属性,让浏览器立即执行回流,因为获取布局属性相关的信息,需要计算,所以可以触发浏览器立即执行回流

比如以下属性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

这里可以采用 DOM.getBoundingClientRect() 也会立即触发回流,强制浏览器重新计算布局,确保它检测到高度变化


最终代码

在这里插入图片描述

  <script>
    let itemTitleEl = document.querySelector('.item_title')
    let dropdownMenuEl = document.querySelector('.dropdown-menu')
    itemTitleEl.addEventListener("mouseenter", function () {
      dropdownMenuEl.style.height = 'auto'

      const { height } = dropdownMenuEl.getBoundingClientRect()
      dropdownMenuEl.style.height = 0
      console.log("mousenter", height)

      dropdownMenuEl.getBoundingClientRect() // 强制浏览器重新计算布局,确保它检测到高度变化
      dropdownMenuEl.style.transition = 'all 1s'
      dropdownMenuEl.style.height = height + 'px'
    })
    itemTitleEl.addEventListener("mouseleave", function () {
      dropdownMenuEl.style.height = 0
    })
  </script>

参考链接

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值