前端如何优雅实现0到auto的高度过渡(隐藏款-程序员BUFF派送福利)
作者:Linsk
各位好,相信大家都知道,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 中没有过渡效果,而是直接隐藏显示,并不影响实际使用,非常地优雅
视频版:【前端如何优雅实现 0到auto 的高度过渡-哔哩哔哩】 b23.tv/KBx7UoQ
…………………………………………………………
“爱码士”集结号,唤醒“猿”气超能力 ——福利暖冬免费派送活动火热进行中
代码工具VIP会员、文创“爱码士”礼包、开心麻花门票等➡派送通道~
😋程序员狂欢继续~~~
- 点赞
- 收藏
- 关注作者
评论(0)