尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Ariakit Animated Disclosure:用纯 CSS 过渡动画实现 Disclosure 内容高度展开与折叠

发布时间:2026/9/25 2:18:39

资讯中心
01
ARTICLE

Ariakit Animated Disclosure:用纯 CSS 过渡动画实现 Disclosure 内容高度展开与折叠

Ariakit Animated Disclosure:用纯 CSS 过渡动画实现 Disclosure 内容高度展开与折叠
UI组件前端【免费下载链接】ariakitToolkit with accessible components, styles, and examples for your next web app项目地址https://gitcode.com/gh_mirrors/ar/ariakit点击查看免费下载本篇指南围绕 Ariakit 仓库中的 Animated Disclosure 示例examples/disclosure-animated展开演示如何在不依赖任何 JS 动画库的前提下通过grid-template-rows过渡实现DisclosureContent高度从0到auto的展开/折叠动画。读完本文你将掌握Disclosure 内容的三层嵌套标记结构为何是必须的、[data-enter]选择器背后的状态机原理、以及aria-expanded驱动的图标旋转动画的完整落地方式。示例总览与完整代码该示例readme的目标非常明确给 Disclosure 组件加上纯 CSS 过渡让内容展开/折叠时高度平滑变化。它基于 WAI-ARIA Disclosure Pattern 构建完整 API 构成如下见 components/disclosure.mduseDisclosureStore() useDisclosureContext() DisclosureProvider Disclosure / DisclosureContent / /DisclosureProvider示例的完整实现见 index.react.tsx核心结构如下import * as Ariakit from ariakit/react; import ./style.css; export default function Example() { return ( div classNamewrapper Ariakit.DisclosureProvider Ariakit.Disclosure classNamebutton What are vegetables? {chevronIcon} /Ariakit.Disclosure Ariakit.DisclosureContent classNamecontent-wrapper div div classNamecontent p Vegetables are parts of plants that are consumed by humans or other animals as food. ... /p /div /div /Ariakit.DisclosureContent /Ariakit.DisclosureProvider /div ); }要点拆解DisclosureProvider创建一个 store把Disclosure触发按钮与DisclosureContent被控制的内容关联起来Disclosure默认渲染为button点击即调用 store 的toggle()切换open状态disclosure.tsxDisclosureContent默认渲染为div由 Ariakit 自动管理其hidden、data-open、data-enter、data-leave等属性。内容标记结构为什么需要两层中间 divCSS 至今不支持对auto值做过渡height: 0 → auto无法插值因此示例采用了一个变通方案用grid-template-rows的可插值特性间接动画高度。为此内容树的组织方式必须遵循特定格式摘自 readmeDisclosureContent classNamecontent-wrapper div div classNamecontent ...三层结构的职责划分层级元素职责外层DisclosureContent.content-wrapper承担 grid 布局与grid-template-rows过渡中间层匿名divgrid 的直接子元素必须overflow: hidden且不能有任何 padding用于裁切折叠时的溢出内容内层.content真正承载内容的 padding因为 padding 放在中间层会导致0fr折叠时仍残留内边距高度readme 特别强调中间div是必需的The intermediatedivis essential因为 grid 的直接子元素不能有 padding——把 padding 移到.content上才能做到真正折叠到 0 高度。用 grid-template-rows 动画内容高度在结构就位后readme给出的核心 CSSSCSS 嵌套写法为.content-wrapper { display: grid; transition: grid-template-rows 150ms; grid-template-rows: 0fr; /* 等价于 height 从 0 过渡到 auto */ [data-enter] { grid-template-rows: 1fr; } /* grid 的直接子元素必须隐藏溢出且无 padding */ * { overflow: hidden; padding: 0; } }原理0fr与1fr是两个可插值的数值grid-template-rows从0fr过渡到1fr时grid 轨道的高度会随内容高度连续变化视觉上完全等效于height: 0 → auto的过渡。仓库中该示例的真实实现使用了 Tailwind 原子类style.css两者完全等价.content-wrapper { apply grid grid-rows-[0fr] transition-[grid-template-rows] duration-200 >props { data-open: open || undefined, data-enter: transition enter || undefined, data-leave: transition leave || undefined, hidden, ...props, };其背后的状态机值得理解DisclosureContent渲染后store 的animated状态被置为truedisclosure-content.tsx组件通过双重requestAnimationFrameafterPaint等待元素真正落屏后再根据open/mounted判定把内部 transition 状态设为enter或leave从而挂载data-enter/data-leave属性disclosure-content.tsx。双重 rAF 是为了避免属性在元素完成渲染前被加上导致过渡不触发动画结束后组件通过读取getComputedStyle中的transition-duration、animation-duration等计算最长结束时间getElementEndTime用超时器清除动画状态如果检测到超时为 0没有定义任何过渡会直接把animated置回false元素在关闭时立即卸载、跳过离场动画disclosure-content.tsx内容不可见时mounted false等组件会给元素加上display: none内联样式与hidden属性保证动画结束后内容从可访问性树和布局中彻底移除disclosure-content.tsx。这也解释了为什么样式只需写在[data-enter]一个选择器上进入时 Ariakit 加上data-enter使grid-template-rows变为1fr当open变为false后属性被移除过渡自动反向回落到0fr完成折叠。浏览器支持grid-template-rows的可动画性已获所有现代浏览器支持。在旧浏览器中内容会直接出现/消失而不播放动画——这是 readme 中明确说明的优雅降级行为不会导致功能损坏。旋转 Disclosure 箭头图标展开/折叠的第二个视觉反馈是按钮上箭头图标的旋转。示例使用 CSS 的rotate属性配合aria-expanded选择器实现摘自 readme.button svg { transition: rotate 150ms; [aria-expandedtrue] { rotate: 180deg; } }对应的 Tailwind 写法见 style.css.button { apply ... [svg]:transition-[rotate] [svg]:aria-expanded:[rotate:180deg] }aria-expanded属性由 Ariakit 自动维护从 disclosure.tsx 可以看到Disclosure会合并出aria-expanded: expanded与aria-controls: contentElement?.id其中expanded由 store 的open状态驱动。因此图标动画不需要任何 JS 状态——只要open变化aria-expanded变化CSS 过渡即自动触发。这正是 WAI-ARIA Disclosure Pattern 要求触发器携带aria-expanded的可访问性收益在视觉层的一次复用样式指南另见 guide/200-styling/readme.md。小结与相关示例该方案的价值在于动画完全由 CSS 声明式驱动Ariakit 只负责在正确的时机挂载data-enter/data-leave与aria-expanded等语义属性且内置了动画时长探测与降级逻辑——没有动画的浏览器环境下内容直接显隐功能不受影响。同一套思路在仓库中还有多组变体可以参考动画 Dialogexamples/dialog-animated/index.react.tsx动画 Selectexamples/select-animated/index.react.tsx动画 Comboboxexamples/combobox-animated/index.react.tsx动画 Tab Panelexamples/tab-panel-animated/index.react.tsx基于 Framer Motion 的 Menuexamples/menu-framer-motion/index.react.tsx基于 Framer Motion 的 Tooltipexamples/tooltip-framer-motion/index.react.tsx需要说明的适用前提本示例代码文件标注为 Ariakit Plus 许可见 index.react.tsx 头部注释但其中演示的grid-template-rowsdata-enter技术方案与组件本身的用法同样适用于ariakit/react的Disclosure/DisclosureContent组件。赞分享UI组件前端【免费下载链接】ariakitToolkit with accessible components, styles, and examples for your next web app项目地址https://gitcode.com/gh_mirrors/ar/ariakit点击查看免费下载相关推荐OpenFoodFacts-androidapp架构深度剖析现代Android应用的多变体设计实践OpenFoodFacts androidapp架构深度剖析现代Android应用的多变体设计实践 OpenFoodFacts androidapp是一个基于HP-Socket开源项目合作伙伴权益与义务清单明确责任边界HP Socket开源项目合作伙伴权益与义务清单明确责任边界 HP Socket作为高性能TCP/UDP/HTTP通信组件已经成为众多企业和开发者构建高并发后端网络通信Ariakit Combobox 动画实战用 CSS Transitions 实现优雅过渡的下拉框Ariakit Combobox 动画实战用 CSS Transitions 实现优雅过渡的下拉框 本篇以 Ariakit 仓库中的 combobox aniUI组件前端上一篇OpenSwiftUI跨平台的SwiftUI开源实现下一篇终极指南如何用HunterPie v2提升你的怪物猎人游戏体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。