Research note / 2026/06/22

Dialog 入场动画序列

一种将背景遮罩与面板内容分两阶段编排的 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 登录请求。