不定高元素动画实现方案(上)

前情

最近接了一个需求,需要实现一个列表,列表可展开收起,展开收起需要有一个动画效果,而列表个数不定且每项内容高度也不固定,所以是一个不定高的收起展开效果,我尝试了如下几中方式,最后选择了我觉得最佳的

通过max-height来实现

其实把高度设为auto,可以让元素高度撑开,但是auto是不会有动画效果的,此时我们可以把max-height设为一个较大的值,这样就实现动画效果了

代码如下:

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div class="container">
    <div class="inner">
      <div class="header">header</div>
      <ul class="list">
        <li>111111111</li>
        <li>2222222222</li>
        <li>333333333</li>
      </ul>
    </div>
  </div>
</body>
</html>
html 复制代码
*{
  margin: 0;
  padding: 0;
}
.container{
  width: 100%;
  max-height: 48px;
  overflow: hidden;
  transition:max-height .4s;
}
.container:hover{
  max-height: 111px;
}
.header{
  width: 100%;
  height: 48px;
  background-color: #ccc;
  display: flex;
  align-items: center;
  justify-content: center;
}
.list{
  background-color: green;
}

演示地址:https://jsbin.com/cedifocuci/edit?html,css,output

注意:

max-height设的太高动画效果会太快,设的太小又无法适配所有高度,此方案只能说是能解决问题,但是不是最理想的方案

通过Grid布局来实现

通过网络布局,一开始设置grid-template-rows为0fr,这里有一些技巧,如果子元素有内容,0fr是不生效的,要给子元素设置min-height为0;如果初始要有基础高度,可以设置min-height为指定高度来实现基础高度,此处为48px

关键代码如下:

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div class="container">
    <div class="inner">
      <div class="header">header</div>
      <ul class="list">
        <li>Grid111111111</li>
        <li>Grid2222222222</li>
        <li>Grid333333333</li>
        <li>Grid444444444</li>
      </ul>
    </div>
  </div>
</body>
</html>
css 复制代码
*{
  margin: 0;
  padding: 0;
}
.container{
  width: 100%;
  display: grid;
  grid-template-rows: 0fr;
  min-height: 48px;
  overflow: hidden;
  transition:all .4s;
}
.inner{
  min-height: 0;
}
.container:hover{
  grid-template-rows: 1fr;
}
.header{
  width: 100%;
  height: 48px;
  background-color: #ccc;
  display: flex;
  align-items: center;
  justify-content: center;
}
.list{
  background-color: green;
}

演示地址:https://jsbin.com/xasuviputo/edit?html,css,output

注意:

主流浏览器都支持,但是部分国内浏览器还是有很大兼容问题,如果对兼容性有很高要求的话此方案就不合适了,同时如果你有基础高度,那基础高度的那一段是没有动画效果的

通过clip-path来实现

clip-path 又叫CSS裁剪路径,clip-path 属性用于创建一个元素的可视区域,区域内的内容会显示,而区域外的内容则会被隐藏。这个属性可以用来对元素进行形状裁剪,实现各种视觉效果

此处使用clip-path:inset()来实现,可以传入四个数字inset(1 2 3 4),它们的规则如下图

关键代码如下:

html 复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div class="container">
    <div class="inner">
      <div class="header">header</div>
      <ul class="list">
        <li>clip-path111111111</li>
        <li>clip-path2222222222</li>
        <li>clip-path333333333</li>
        <li>clip-path444444444</li>
      </ul>
    </div>
  </div>
</body>
</html>
css 复制代码
*{
  margin: 0;
  padding: 0;
}
.container{
  width: 100%;
  clip-path: inset(0 0 calc(100% - 48px) 0);
  overflow: hidden;
  transition:all .4s;
}
.container:hover{
  clip-path: inset(0 0 0 0);
}
.header{
  width: 100%;
  height: 48px;
  background-color: #ccc;
  display: flex;
  align-items: center;
  justify-content: center;
}
.list{
  background-color: green;
}

演示地址:https://jsbin.com/zelopuyuxi/edit?html,css,output

注意:

主流浏览器都支持,但是部分国内浏览器还是有很大兼容问题,如果对兼容性有很高要求的话此方案就不合适了,相比grid此方案不会有基础高度无过渡效果的问题

小结

对于做技术的我们,每天都是提出问题解决问题的一个过程,过程中会尝试各种方案,因为解决问题的方案千千万,此篇文章记录了实现不定高内容过渡效果的三种实现方式,怕篇幅太长,此文暂时写这么多,下篇继续......

相关推荐
北海-cherish39 分钟前
vue中的 watchEffect、watchAsyncEffect、watchPostEffect的区别
前端·javascript·vue.js
2501_915909062 小时前
HTML5 与 HTTPS,页面能力、必要性、常见问题与实战排查
前端·ios·小程序·https·uni-app·iphone·html5
white-persist3 小时前
Python实例方法与Python类的构造方法全解析
开发语言·前端·python·原型模式
新中地GIS开发老师3 小时前
Cesium 军事标绘入门:用 Cesium-Plot-JS 快速实现标绘功能
前端·javascript·arcgis·cesium·gis开发·地理信息科学
Superxpang3 小时前
前端性能优化
前端·javascript·vue.js·性能优化
Rysxt_3 小时前
Element Plus 入门教程:从零开始构建 Vue 3 界面
前端·javascript·vue.js
隐含4 小时前
对于el-table中自定义表头中添加el-popover会弹出两个的解决方案,分别针对固定列和非固定列来隐藏最后一个浮框。
前端·javascript·vue.js
大鱼前端4 小时前
Turbopack vs Webpack vs Vite:前端构建工具三分天下,谁将胜出?
前端·webpack·turbopack
你的人类朋友4 小时前
先用js快速开发,后续引入ts是否是一个好的实践?
前端·javascript·后端