CSS实现展开动画

展开收起效果是比较常见的一种交互方式,通常的做法是控制display属性值在none和其它值之间切换,虽说功能可以实现,但是效果略显生硬,所以会有这样的需求——希望元素展开收起能具有平滑的效果。

实现

max-height

首先想到的是通过height0auto之间切换,但是结果可能并不会是我们所预期的那样,原因是我们将要展开的元素内容是动态的,即高度值不确定,因此height使用的值是默认的auto,从0pxauto是无法计算的,因此无法形成过渡或动画效果。

据此我们可以使用max-height,将max-height0过渡到一个能够大于完全显示内部元素的值,展开后的max-height值,只需要设定为保证比展开内容高度大的值即可,在max-height值比height值大的情况下,元素仍会默认采用自身的高度值即auto,如此一来一个高度不定的元素展开收起动画效果就实现了。

请注意这种方式实现还是有限制的,使用CSS进行过渡动画的时候依旧是通过计算0到设定的max-height高度值进行计算的,在实际应用中如果max-height值太大,在元素收起的时候将会产生延迟的效果,这是因为在收起时,max-height从设定的特别大的值,到元素自身高度值的变化过程将占用较多时间,此时画面表现则会产生延迟的效果。因此建议将max-height值设置为足够安全的最小值,这样在收起时即使有略微延迟,也会因为时间很短,难以被用户感知,将不会影响体验。

<!DOCTYPE html>
<html>
<head>
<title>展开动画</title>
<style type="text/css">
.page{
width: 200px;
padding: 10px 20px;
border: 1px solid #eee;
}
.container {
overflow: hidden;
}
.container > .options{
transition: all .5s;
max-height: 0;
}
.container > .unfold{
max-height: 150px;
}
.container > .btn{
color: #4C98F7;
cursor: pointer;
text-decoration: underline;
}
</style>
</head>
<body>
<div class="page">
<div class="container">
<div class="btn" onclick="operate(this)" unfold="1">展开</div>
<div class="options">
<div class="option">选项1</div>
<div class="option">选项2</div>
<div class="option">选项3</div>
<div class="option">选项4</div>
<div class="option">选项5</div>
<div class="option">选项6</div>
<div class="option">选项7</div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
function operate(btn){
const optionsNode = document.querySelector(".container > .options");
const unfold = btn.getAttribute("unfold");
if(unfold && unfold==="1"){
btn.innerText = "收缩";
optionsNode.classList.add("unfold");
}else{
btn.innerText = "展开";
optionsNode.classList.remove("unfold");
}
btn.setAttribute("unfold", unfold === "0" ? "1" : "0");
}
</script>
</html>

height

使用max-height必定有一定的局限性,那么不如我们在DOM加载完成后就取得元素的实际高度并保存,之后直接利用这个真实高度与0进行动画过渡即可,因为浏览器的渲染顺序,在解析JavaScript时会阻塞DOM的渲染,所以在获取元素实际高度再设置高度为0的过程中一般不会出现闪烁的情况,如果实在担心因为获取高度之后再将高度设置为0可能会有一个闪烁的过程,那么我们可以取得元素父节点后调用cloneNode(true)方法或者innerHTML方法取得字符串再innerHTML到一个新创建的节点,目的就是将其拷贝,之后将其使用绝对定位等放置到屏幕外即将其设置到屏幕能够显示的外部区域,注意此时要设置bodyoverflow: hidden;,之后利用getComputedStyle取得实际高度,然后再将其移出DOM结构,此时有了实际高度就可以进行动画过渡了,下面简单的实现一下在DOM加载时便取得实际高度进行动画实现。

<!DOCTYPE html>
<html>
<head>
<title>展开动画</title>
<style type="text/css">
.page{
width: 200px;
padding: 10px 20px;
border: 1px solid #eee;
}
.container {
overflow: hidden;
}
.container > .options{
transition: all .5s;
}
.container > .btn{
color: #4C98F7;
cursor: pointer;
text-decoration: underline;
}
</style>
</head>
<body>
<div class="page">
<div class="container">
<div class="btn" onclick="operate(this)" unfold="1">展开</div>
<div class="options">
<div class="option">选项1</div>
<div class="option">选项2</div>
<div class="option">选项3</div>
<div class="option">选项4</div>
<div class="option">选项5</div>
<div class="option">选项6</div>
<div class="option">选项7</div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
(function init(win, doc){
const optionsNode = document.querySelector(".container > .options");
optionsNode.setAttribute("real-height", win.getComputedStyle(optionsNode).height);
optionsNode.style.height = "0px";
})(window, document); function operate(btn){
const optionsNode = document.querySelector(".container > .options");
const unfold = btn.getAttribute("unfold");
const realHeight = optionsNode.getAttribute("real-height");
if(unfold && unfold==="1"){
btn.innerText = "收缩";
optionsNode.style.height = realHeight;
}else{
btn.innerText = "展开";
optionsNode.style.height = "0px";
}
btn.setAttribute("unfold", unfold === "0" ? "1" : "0");
}
</script>
</html>

translateY

还有一种常用实现动画的方式,即首先将外层元素没有动画过渡的形式直接展开,再将选项加入动画缓慢下落,通常利用transform: translateY();去实现这个缓慢下降的动画,在微信的WEUI小程序组件库的首页就是采用这种实现方式。

<!DOCTYPE html>
<html>
<head>
<title>展开动画</title>
<style type="text/css">
.page{
width: 200px;
padding: 10px 20px;
border: 1px solid #eee;
}
.container, .options-container {
overflow: hidden;
}
.options-container{
height: 0;
}
.container .options{
transition: all .5s;
transform: translateY(-100%);
}
.container .unfold{
transform: translateY(0);
}
.container > .btn{
color: #4C98F7;
cursor: pointer;
text-decoration: underline;
}
</style>
</head>
<body>
<div class="page">
<div class="container">
<div class="btn" onclick="operate(this)" unfold="1">展开</div>
<div class="options-container">
<div class="options">
<div class="option">选项1</div>
<div class="option">选项2</div>
<div class="option">选项3</div>
<div class="option">选项4</div>
<div class="option">选项5</div>
<div class="option">选项6</div>
<div class="option">选项7</div>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
function operate(btn){
const optionsNode = document.querySelector(".container .options");
const optionsContainer = document.querySelector(".options-container");
const unfold = btn.getAttribute("unfold");
if(unfold && unfold==="1"){
btn.innerText = "收缩";
optionsNode.classList.add("unfold");
optionsContainer.style.height = "auto";
}else{
btn.innerText = "展开";
optionsNode.classList.remove("unfold");
optionsContainer.style.height = "0px";
}
btn.setAttribute("unfold", unfold === "0" ? "1" : "0");
}
</script>
</html>

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

http://www.111com.net/wy/192615.htm
https://zhuanlan.zhihu.com/p/52582555
https://cloud.tencent.com/developer/article/1499033

CSS实现展开动画的更多相关文章

  1. jQuery鼠标悬停3d菜单展开动画

    效果体验:http://hovertree.com/texiao/jquery/93/ 竖直的主菜单贴着页面左侧,当光标移入菜单项时,以3D动画的方式弹出对应的二级菜单.采用jQuery和CSS3实现 ...

  2. 为网格布局图片打造的超炫 CSS 加载动画

    今天,我想与大家分享一些专门为网格布局的图像制作的很酷的 CSS 加载动画效果.您可以把这些效果用在你的作品集,博客或任何你想要的网页中.设置很简单.我们使用了下面这些工具库来实现这个效果: Norm ...

  3. 一个纯CSS DIV天气动画图标【转扒的】

    <p> </p> <style><!-- /* SUNNY */ .sunny { -webkit-animation: sunny 15s linear i ...

  4. WPF(C#) 矩阵拖动、矩阵动画、边缘展开动画处理。

    最近在研发新的项目,遇到了一个桌面模式下的难点--展开动画.之前动画这方面没做过,也许很多人开始做的时候也会遇到相关问题,因此我把几个重点及实际效果图总结展示出来: 我的开发环境是在VS2017下进行 ...

  5. CSS图片翻转动画技术详解

    因为不断有人问我,现在我补充一下:IE是支持这种技术的!尽管会很麻烦.需要做的是旋转front和back元素,而不是旋转整个容器元素.如果你使用的是最新版的IE,可以忽略这一节.IE10+是支持的,I ...

  6. JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能

    摘要: 理解浏览器渲染. 原文:JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这是专门探索 J ...

  7. 简单的CSS圆形缩放动画

    简单的CSS圆形缩放动画 话不多说鼠标移动上去,看效果吧,效果预览 代码如下: <!DOCTYPE html> <html> <head> <title> ...

  8. 网页DIV+CSS布局和动画美化全程实例 (陈益材) 随书光盘

    网站的建站技术近几年得到迅速的发展,网页的布局与特效动画技术层出不穷,网站建设已经从简单的技术支持时代衍变到现在的视觉美化时代.但如何使设计的网页高人一筹,达到让人过目不忘的境界,如何追求以最简单的特 ...

  9. animate.css引入实现动画效果

    最近在网上看到很多代码都通过引入animate.css来实现动画效果,后来我便使用这种方法来尝试着写了个小案例,结果真的很好用,比我们通常情况下使用css或js实现动画效果好得多,便在此做个总结. 第 ...

  10. How Javascript works (Javascript工作原理) (十三) CSS 和 JS 动画底层原理及如何优化其性能

    个人总结:读完这篇文章需要20分钟. 这是 JavaScript 工作原理的第十三章. 概述 正如你所知,动画在创建令人叹服的网络应用中扮演着一个关键角色.由于用户越来越注重用户体验,商户开始意识到完 ...

随机推荐

  1. 【Git】用法小记

    解决windows环境下的CRLF与unix环境下的LF问题,windows提交时CRLF=>LF,签出时LF=>CRLF,unix环境保留 git config --global cor ...

  2. [转帖]聊聊TPS、QPS、CPS概念和区别

    https://cloud.tencent.com/developer/article/1859053 TPS 概念 TPS:是TransactionsPerSecond的缩写,也就是事务数/秒.它是 ...

  3. [转帖]什么是ClickHouse?

    什么是ClickHouse? ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS). 在传统的行式数据库系统中,数据按如下顺序存储: Row WatchID JavaEn ...

  4. [转帖]深入理解mysql-第十章 mysql查询优化-Explain 详解(上)

    目录 一.初识Explain 二.执行计划-table属性 三.执行计划-id属性 四.执行计划-select_type属性 一条查询语句在经过MySQL查询优化器的各种基于成本和规则的优化会后生成一 ...

  5. [转帖]最全MySQL锁讲解:页锁、共享锁、行锁、表锁、悲观锁、乐观锁

    我们在操作数据库的时候,可能会由于并发问题而引起的数据的不一致性(数据冲突),如何保证数据并发访问的一致性.有效性,是所有数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素,从 ...

  6. [转帖]JVM 问题诊断快速入门

    https://zhuanlan.zhihu.com/p/110197145 JVM 全称为 Java Virtual Machine,翻译为中文 "Java 虚拟机".本文中的J ...

  7. MySQL控制权限

    编写顺序和执行顺序是不一样的 编写顺序: SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后条件列表 ORDER BY 排序字段列表 ...

  8. 数据仓库(4)基于维度建模的数仓KimBall架构

      基于维度建模的KimBall架构,将数据仓库划分为4个不同的部分.分别是操作型源系统.ETL系统.数据展现和商业智能应用,如下图.   操作型源系统,指的就是面向用户的各类系统,如app.网站.E ...

  9. Map结构映射,避免每一个字段赋值

    var query1 = (from fore in forecastShippingDate join ship in shipOutOfStock on fore.Id equals ship.F ...

  10. 使用Navicat 进行MySql数据库同步功能

    使用Navicat 进行MySql数据库同步功能 作者:胡德安 准备: 打开Navicat管理工具(比如Navicat Premium 15管理工具) 两个数据库第一个是源数据库A和要被同步的目标数据 ...