Research note / 2026/06/22
Dialog 入场动画序列
一种将背景遮罩与面板内容分两阶段编排的 Dialog 入场动画序列。

概述
一种将背景遮罩与面板内容分两阶段编排的 Dialog 入场动画序列。
其核心特征是:
- 阶段 1:背景遮罩以 64px 重度模糊淡入(0.4s),让背后内容完全失焦;
- 阶段 2:面板内容从下方 24px 处弹入并伴随 3% 缩放恢复(0.6s);
- 两个动画同时开始但时长不同,用户的注意力自然从”背景模糊”过渡到”内容出现”;
- 面板采用 Double-Bezel 嵌套结构,外壳白色半透明、内核毛玻璃。
两阶段入场
阶段 1:背景遮罩(fade-in)
<div className="fixed inset-0
bg-foreground/20 backdrop-blur-3xl /* 20% 暗 + 64px 模糊 */
animate-fade-in" /* 0.4s ease-luxe */
onClick={onClose} />
backdrop-blur-3xl= 64px 模糊,让背后内容完全失焦animate-fade-in= 0.4s 的淡入,使用ease-luxe曲线
阶段 2:面板内容(slide-up-spring)
<div className="animate-slide-up-spring"> /* 0.6s ease-bezel */
{children}
</div>
@keyframes slide-up-spring {
from {
opacity: 0;
transform: translateY(24px) scale(0.97); /* 下方 24px + 缩小 3% */
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.animate-slide-up-spring {
animation: slide-up-spring 0.6s var(--ease-bezel) both;
}
时序关系
0ms 遮罩开始淡入(0.4s)
~0ms 面板开始上移+弹入(0.6s)
400ms 遮罩淡入完成
600ms 面板弹入完成
两个动画同时开始,但遮罩更快完成(0.4s vs 0.6s),让用户的注意力自然从”背景模糊”过渡到”内容出现”。
Double-Bezel 面板结构
{/* 外壳 — 白色半透明边框(因为叠在模糊背景上) */}
<div className="p-1.5 rounded-[2rem]
bg-white/[0.12] ring-1 ring-white/[0.15]">
{/* 内核 — 毛玻璃内容区 */}
<div className="rounded-[calc(2rem-0.375rem)]
bg-card/95 backdrop-blur-xl
shadow-[inset_0_1px_1px_rgba(255,255,255,0.2),
0_24px_80px_-12px_rgba(0,0,0,0.12)]
p-8">
{children}
</div>
</div>
注意:Dialog 的外壳用 bg-white/[0.12](亮色半透明),而非 Card 的 bg-black/[0.03](暗色半透明),因为 Dialog 叠在暗色模糊背景上。
关闭按钮
<button className="absolute right-4 top-4 z-10
h-8 w-8 rounded-xl
bg-foreground/[0.04] ring-1 ring-black/[0.06]
hover:bg-foreground/[0.08] hover:text-foreground
transition-all duration-300
[transition-timing-function:var(--ease-out-expo)]">
<X className="h-4 w-4" />
</button>
交互细节
- Escape 关闭:
useEffect监听keydown - 点击遮罩关闭:
onClick={onClose}+e.stopPropagation()防止穿透 - Focus Trap:打开时自动 focus 第一个可聚焦元素
适用场景
- 任何需要”从下方弹出”的浮层
- 替代传统的
scale(0.95)弹入,translateY + scale组合更有层次感 - 配合 64px 重模糊背景,制造”聚焦当前任务”的沉浸感
Discussion
评论
站点尚未配置 GitHub Discussions。文章阅读不受影响,也不会再发起无效的 GitHub 登录请求。