前端如何优雅实现0到auto的高度过渡

简介: 各位好,相信大家都知道,最近更新 Chrome 已经支持了 0 到 auto 的高度过渡。但是很多人反映这种特性太新了,出于兼容考虑用不了的。而实际上 calc-size 是可以渐进增强的。今天我就给大家表演一下,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 中没有过渡效果,而是直接隐藏显示,并不影响实际使用,非常地优雅

视频版:【前端如何优雅实现 0到auto 的高度过渡-哔哩哔哩】 https://b23.tv/KBx7UoQ

目录
相关文章
|
10天前
|
人工智能 安全 Linux
【OpenClaw保姆级图文教程】阿里云/本地部署集成模型Ollama/Qwen3.5/百炼 API 步骤流程及避坑指南
2026年,AI代理工具的部署逻辑已从“单一云端依赖”转向“云端+本地双轨模式”。OpenClaw(曾用名Clawdbot)作为开源AI代理框架,既支持对接阿里云百炼等云端免费API,也能通过Ollama部署本地大模型,完美解决两类核心需求:一是担心云端API泄露核心数据的隐私安全诉求;二是频繁调用导致token消耗过高的成本控制需求。
5494 13
|
18天前
|
人工智能 JavaScript Ubuntu
5分钟上手龙虾AI!OpenClaw部署(阿里云+本地)+ 免费多模型配置保姆级教程(MiniMax、Claude、阿里云百炼)
OpenClaw(昵称“龙虾AI”)作为2026年热门的开源个人AI助手,由PSPDFKit创始人Peter Steinberger开发,核心优势在于“真正执行任务”——不仅能聊天互动,还能自动处理邮件、管理日程、订机票、写代码等,且所有数据本地处理,隐私完全可控。它支持接入MiniMax、Claude、GPT等多类大模型,兼容微信、Telegram、飞书等主流聊天工具,搭配100+可扩展技能,成为兼顾实用性与隐私性的AI工具首选。
21826 117
|
14天前
|
人工智能 安全 前端开发
Team 版 OpenClaw:HiClaw 开源,5 分钟完成本地安装
HiClaw 基于 OpenClaw、Higress AI Gateway、Element IM 客户端+Tuwunel IM 服务器(均基于 Matrix 实时通信协议)、MinIO 共享文件系统打造。
8302 8

热门文章

最新文章