CSS 机制与完整配方
来源:css-animations/SKILL.md、css-animations/RECIPES.md、animate/css-techniques.md。已讲内容全部收入,本章可独立复习。
2.1 选择 transition 还是 keyframes
Transition 适合状态变化、反复开关和 hover;keyframes 适合循环、独立序列和一次性入场。不要把“用户触发/页面触发”当绝对分界,真正要看状态是否会在中途改变、是否需要多阶段时间线。
把 transition 写在基础状态,才能让进入和返回都使用它;明确 property,避免 all 把意外的尺寸/定位变化也带入。延迟独立写,复杂 shorthand 更容易读错。
.visual {
transition: transform 180ms cubic-bezier(0.19, 1, 0.22, 1),
opacity 180ms ease;
transition-delay: 0ms;
}
2.2 Keyframes 的生命周期
backwards 在等待 delay 时应用起始关键帧;forwards 在结束后保留结束关键帧;both 同时应用。Forwards 不是入场必需条件:普通 CSS 已是最终状态时,无需长期保留动画覆盖。
infinite 循环,alternate 往返,animation-play-state: paused 暂停。没写 0%/100% 时可由底层样式补足端点,但复杂合成与多个动画叠加时要明确检查实际 computed style。改变 React key 可以重挂载重播,同时也会重置表单和局部状态,不适合无意使用。
2.3 首次入场与退出
新插入节点没有之前的样式供 transition 比较,@starting-style 可以提供首次起始样式:
.notice {
opacity: 1;
transform: translateY(0);
transition: opacity 180ms ease-out, transform 180ms ease-out;
@starting-style {
opacity: 0;
transform: translateY(12px);
}
}
它不负责延迟 React 卸载。节点已经移除时,CSS 没有可绘制的内容;需由 presence 管理、组件原语的退出支持,或明确的挂载生命周期处理。涉及 display/top layer 的过渡另需离散过渡与退出可见性处理,不要把 starting-style 当完整弹窗方案。实现时检查目标浏览器与静态回退。MDN 说明。
2.4 Transform 的参考系与组合
普通 HTML 元素的百分比 translate 通常相对自身参考盒;scale 会缩放文字、图标和圆角,不改变文档流占位。不同高度 Toast 不能只用各自高度乘序号来累计堆叠。
translateX(100px) rotate(90deg) 与 rotate(90deg) translateX(100px) 不同。矩阵作用于点时右侧先作用;后者的中心位移会落在旋转后的轴向。定位、缩放反馈、旋转分层处理可以避免覆盖。普通非替换 inline 元素无法直接变换,文字单元可用 inline-block;这不意味着 span “没有盒子”。
2.5 Hover 与按压
外层负责命中,内层抬升,避免移出命中范围后反复触发。Hover 动效放进 (hover: hover) and (pointer: fine) 能力查询;关键内容还需要键盘与点击入口。:focus-visible 是浏览器对需要可见焦点的判断,不只等同于键盘;包含内部控件的卡片还要考虑 :focus-within。
.card .inner { transition: transform 150ms ease-out; }
@media (hover: hover) and (pointer: fine) {
.card:hover .inner { transform: translateY(-4px); }
}
.card:focus-within .inner { transform: translateY(-4px); }
@media (prefers-reduced-motion: reduce) {
.card .inner { transform: none; transition: none; }
}
卡片描述可从 translateY(calc(100% + gap + 1px)) 揭示,1px 是源配方为阴影/边界预留的特定修正,不应无条件复制。
2.6 Clip-path:保持内容形状,只改变可见范围
inset(top right bottom left) 从四边裁切;inset(0) 全显,inset(0 100% 0 0) 从右裁掉全部,inset(0 50% 0 0) 隐藏右半边。它保留布局占位,不压缩内部内容,但不保证每种裁切在所有浏览器都只做合成。
图像对比:两张图片重叠,顶层右裁切量由拖动位置控制。揭示动画:保持图片完整,逐渐减少裁切。裁切不是业务隐藏状态,不能单凭它保证控件不可聚焦。
2.7 无缝 Tab 高亮与主题擦除
原配方把整组 Tab 复制成“全部激活的样子”,再裁切到实际激活区域;移动裁切窗口时文字颜色天然正确,不必同步每个字的颜色过渡。代价是重复 DOM、测量和维护。复制层应纯展示、无重复 ID/焦点/读屏内容,交互保留在原层。
主题擦除也可以叠两份主题后裁切,但复制整页成本大,可能破坏表单/状态。原文将其作为原型技巧;生产方案需按项目情况考虑原生 View Transitions,并保留直接切换回退。
2.8 文字揭示与错峰
固定裁切窗包裹运动的字/词,单元 inline-block、外层 overflow hidden、起点 translateY(100%)、延迟期 backwards。30ms/字也是会累积的:长标题应按词分组、限制总延迟。拆字保留完整文本语义,避免读屏逐字重复、换行被锁死。
.word { display: inline-block; overflow: hidden; }
.word > span {
display: inline-block;
animation: rise 300ms cubic-bezier(0.19,1,0.22,1) backwards;
animation-delay: calc(var(--index) * 30ms);
}
@keyframes rise { from { transform: translateY(100%); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .word > span { animation: none; } }
2.9 两份箭头接力
下载箭头 A 从窗口上方移到中央,B 从中央移到下方;两份图标在同一裁切窗中,同曲线同时运动,形成持续向下的错觉。源配方使用 ±150% 避免边缘露出。展示副本不进入可访问树;键盘也应能得到相同反馈。
2.10 Toast 与堆叠卡片
新 Toast 入场和已有 Toast 让位是两个运动:先给新节点起始位置,已有节点根据 stack index 过渡到新位置。连续加入时要从当前画面继续,不能给整组重播 keyframes。静态等高配方可按序号计算,高度可变需测量。
折叠卡片栈可用 index 派生 translateY、scale、z-index,并把原点设在同一边。注意 transform 不改变布局,父容器高度与可点区域要单独管理,后排卡片不应无意接收焦点。
2.11 长按删除
覆盖层从 inset(0 100% 0 0) 揭示到 inset(0);按住时 1.5s linear,松开时约 0.2s ease-out 退回。按钮按压另用 scale(0.97)。视觉进度不执行删除;完成条件、取消、pointercancel、失焦和键盘方式由逻辑处理。关键删除通常还需要撤销或其他适合风险的保护。
2.12 跑马灯、闪烁与循环
重复内容无缝循环时,位移距离必须等于一个重复单元的完整长度,包括间距,否则接缝跳变。光标闪烁可用离散 steps 而非慢慢淡化。循环要能暂停;装饰性循环在 reduce 下关闭,复制内容避免重复朗读。
2.13 3D 轨道与硬币
Perspective 产生近大远小;preserve-3d 保留相关子层的三维关系;translateZ 改变深度;backface-visibility 控制背面。它们各司其职。
轨道配方:绕 Y 轴旋转→沿 Z 轴偏移→反向旋转图标,使其绕轨道但保持朝向。硬币配方:正面沿 Z 微移,背面 rotateY(180deg) 再偏移,容器持续 rotateY。深度与透视值是场景参数,不是通用常数。部分分组属性会让 3D 子树扁平化,异常遮挡时检查祖先样式。
2.14 如何逆向学习
观察参考→记录触发条件→DevTools 查属性/时长/曲线→慢放找关键帧→用最小例子复现→正常速度比较。截图看不到延迟、中断和惯性,不能只照截图复制动画。
自测与答案
-
为什么文字等待 delay 时先闪出来?起始关键帧没有覆盖等待期,检查 backwards。
-
CSS 入场能播放,React 退出不能?检查是否立即卸载及 presence 包裹位置。
-
translateY(100%) 能自动计算整个异高 Toast 栈吗?不能,它只知道自己的参考盒。
-
Clip-path 揭示与 scaleX 区别?前者裁切,后者会压缩内容。
-
两份图标技巧的成本?重复内容管理、裁切边界与无障碍处理。
来自作者已整理的 Skills 中文自学资料。数字和配方是调试起点,库与浏览器的行为需结合实际版本验证;教材中的原演示验收记录不等同于你的项目已通过测试。
技术校正与版本边界 ↗完整来源说明 ↗