前端如何优雅实现0到auto的高度过渡
各位好,相信大家都知道,最近更新Chrome已经支持了0到auto的高度过渡。但是很多人反映这种特性太新了,出于兼容考虑用不了的。而实际上calc-size是可以渐进增强的。今天我就给大家表演一下,0到auto的渐进增强兼容所有浏览器。
我们先搭建一个空白工程化项目
这个示例工程。是一个计数器。
import * as React from "react"; import { Component } from "react"; interface AppProps { } interface AppState { count: number; } export default class App extends Component<AppProps, AppState> { constructor(props: AppProps) { super(props); this.increase = this.increase.bind(this); this.decrease = this.decrease.bind(this); this.state = { count: 0 }; } private decrease() { this.setState({ count: this.state.count - 1 }); } private increase() { this.setState({ count: this.state.count + 1 }); } render() { var { count } = this.state; return <> <h1>Hello World!</h1> <div> <button type="button" onClick={this.decrease}>-</button> {count} <button type="button" onClick={this.increase}>+</button> </div> </>; } }
接下来我们创建一个组件
这个组件有展开和收起2种状态。修改传入的属性,可以切换className
import * as React from "react"; import { Component } from "react"; import "./CollapseBody.scss"; export interface CollapseBodyProps { open?: boolean; } export class CollapseBody extends Component<CollapseBodyProps> { render() { let { open, children } = this.props; let classList = ["collapse-body"]; if(open) { classList.push('collapse-body_open'); } else { classList.push('collapse-body_close'); } return <div className={classList.join(" ")}> {children} </div>; } }
接下来我们引入组件
直接在刚刚的计数器上改一下,这样在计数的时候就会切换展开收起状态。
import * as React from "react"; import { Component } from "react"; import { CollapseBody } from "./Components/Collapse/CollapseBody"; interface AppProps { } interface AppState { count: number; } export default class App extends Component<AppProps, AppState> { constructor(props: AppProps) { super(props); this.increase = this.increase.bind(this); this.decrease = this.decrease.bind(this); this.state = { count: 0 }; } private decrease() { this.setState({ count: this.state.count - 1 }); } private increase() { this.setState({ count: this.state.count + 1 }); } render() { var { count } = this.state; return <> <h1>Hello World!</h1> <div> <button type="button" onClick={this.decrease}>-</button> {count} <button type="button" onClick={this.increase}>+</button> </div> <CollapseBody open={count % 2 === 0}> asdasdas </CollapseBody> </>; } }
接下来我们看看效果
我们可以看到按钮时class在切换
接下来编写样式
展开时高度是calc-size(auto , size);收起时,高度是0;在加以transition和overflow就完成了。
我们试一下,在高版本正常过渡,低版本由于不支持calc-size(auto, size),于是高度为默认值auto,没有过渡动画,但是不影响使用。
.collapse-body { transition: height .3s; overflow-y: hidden; height: calc-size(auto, size); } .collapse-body_close { height: 0; }
overflow和display优化
上面代码虽然能用但是还不够完美,有2个问题。
- 首先容器含有overflow:hidden,会导致内部内容被截断,如果内部内容还有box-shadow,很容易被截掉。最好是只在过渡时含有overflow:hidden。
- 还有收起后应当含有disaplay:none,否则收起后仍然占据体积,在一些情况下会出现不必要的滚动条。
我们可以使用animation进行改造。
.collapse-body_close { display: none; } @supports(height: calc-size(auto, size)) { .collapse-body_open { animation: collapseBodyIn .3s; } .collapse-body_close { animation: collapseBodyOut .3s; } } @keyframes collapseBodyIn { from { overflow-y: hidden; height: 0; } to { overflow-y: hidden; height: calc-size(auto, size); } } @keyframes collapseBodyOut { from { overflow-y: hidden; display: block; height: calc-size(auto, size); } to { overflow-y: hidden; display: block; height: 0; } }
出现动画
上面示例首次出现时也有动画,假如不想要首次出现的动画,只有切换时才有动画,可以在组件上控制。
import * as React from "react"; import { Component } from "react"; import "./CollapseBody.scss"; export interface CollapseBodyProps { open?: boolean; } export class CollapseBody extends Component<CollapseBodyProps> { private first = true; componentDidMount(): void { this.first = false; } render() { let { open, children } = this.props; let classList = ["collapse-body"]; if(!open) { classList.push('collapse-body_close'); } else if(!this.first) { classList.push('collapse-body_open'); } return <div className={classList.join(" ")}> {children} </div>; } }
最后看看效果
非常的完美
最后我们再看看低版本浏览器的效果
先点构建,我这里配置的构建脚本已经,包含了语法转义和polyfill,也用了anujs,因此react的兼容性可以不用操心,我们只看CSS效果。
我们直接上难度挑战IE6,我们发现在在IE6中没有过渡效果,而是直接隐藏显示,并不影响实际使用,非常地优雅

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
复用的双刃剑:软件工程里的悖论与挑战
在软件工程领域,复用与扩展性一直是开发者追求的目标,然而,这两者之间存在着天然的矛盾。本文探讨了复用的双面性——它既可能是提升效率的利器,也可能是引入复杂性和维护难题的根源。 第二十二条军规 我一直有一个疑惑,「Duplicated code fragment 10 lines long」这是IntelliJ IDEA中对重复代码的标记。我们从学习面向对象开始就被告诫,duplicated code is a bad smell。但当我真正进入复杂工程项目后,我发现往往让我栽跟头的,却是那些被各种所谓“复用”的“抽象”后的“abstracted code” 。 软件工程设计,上至远古大神阿兰·图灵、冯·诺依曼,下至20世纪互联网高度发达的今天,诞生的各种框架与工具,本质上只在朝着2个方向在发展:可复用、可扩展,一对天然矛盾而又长期共存的2个方向。 “你的代码复用性不强”,“如果未来XXX你这里怎么支撑”,“能不能做到新场景0成本接入”,可复用的设计理念像军规一样督导我们编码和开发,可谁又知道它是不是那第二十二条。(美国海军·第二十二条军规) 中台视角看复用的魅力 提到中台就不得不提中台...
- 下一篇
得物iOS函数调用栈及符号化调优实践|得物技术
一、背景 随着《个人信息保护法》等法律法规的逐步发布实施,个人隐私保护受到越来越多人的关注。在这个整体的大背景下,得物持续完善App的各项合规属性,而在这个过程中,绕不开法务、安全、产品、设计、研发、测试几个重要环节,其中研发与测试属于具体落地的最后一环,直接关系到App的隐私合规质量。 伴随得物用户规模和业务复杂度不断提升,应用上线前的隐私合规检测愈发重要;当前得物版本灰度前的合规检测正在向着规模化、自动化发展,其中动态检测的性能和效率瓶颈也越发凸显。 谈到在iOS上获取当前线程的调用栈时,大部分开发者第一个想到的是 +[NSThread callStackSymbols] 。该个方法在日常开发调试带有符号的测试包过程中,可以快速获取符号化之后的堆栈,十分符合当前得物灰度前针对测试包进行动态检测隐私函数调用的场景。 但在实际的使用过程中,当大量且频繁的利用 +[NSThread callStackSymbols] 获取隐私函数调用的符号化堆栈时,CPU的占用率居高不下,造成测试机卡死发热,严重影响正常的回归测试。 因此iOS端符号化堆栈采集的难点变成如何"不卡顿"与"无感知"的获取调...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7安装Docker,走上虚拟化容器引擎之路
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作