微交互动画需以CSS为主、JS为辅,通过transition和@keyframes实现轻量、可感知的反馈,严格遵循性能与兼容性规范。
微交互动画不是“加个动画就完事”,而是让按钮、输入框、加载状态这些小元素在用户操作瞬间给出可感知、有节奏、不打断流程的视觉反馈。核心原则是:CSS 负责绝大多数动效,JS 只做状态切换的“开关”。
这是最轻量、最可靠的方式。关键不是写多炫的动画,而是选对触发属性和 timing-function。
transition 必须写在默认状态(非 :hover 或 :active)里,否则第一次悬停会无过渡transition: all 0.3s —— 它会意外过渡 height、display 等不可动画属性,导致布局抖动transition: background-color 0.2s ease, transform 0.2s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.2s ease
:active 状态要配合 transform: scale(0.98) + background-color 加深,模拟物理按压感;但注意 iOS Safari 对 :active 支持不稳定,需加 cursor: pointer 触发当需要循环、多帧、路径运动(如摇晃、打字、加载旋转)时,@keyframes 不可替代,但 JS 绝不能直接操作 style.animation。
element.classList.add('is-shaking') 触发预设动画类,而不是 element.style.animation = 'shake 0.5s'
animationend 事件移除 class,避免重复触发或状态残留touchstart 和 click,但优先用 touchstart 防 iOS 300ms 延迟;touchstart 中调用 e.preventDefault() 可防止长按唤出菜单干扰animation 和 animation-play-state
直接改 element.style.transform 或 element.style.opacity 看似简单,但极易破坏已有 transition 或 animation 流程。
立即学习“前端免费学习笔记(深入)”;
transition 声明,导致“突然跳变”box.style.transform = 'scale(1.2)' 会立刻生效,没有过渡;而 box.classList.add('is-expanded') 才能触发已声明的 transition: transform 0.3s
box.style.setProperty('--rotate-angle', '45deg'),再由 CSS 的 transform: rotate(var(--rotate-angle)) 驱动过渡<input>)的 :focus 状态动画,也必须靠 class + :focus-within 实现,不能靠 JS 监听 focus 事件去改 style在手机上,微交互卡顿往往不是因为动画复杂,而是触发时机错位或强制同步重排。
touchmove 里直接改 transform —— 它会触发 layout,导致掉帧;改用 requestAnimationFrame 节流,或直接用 CSS will-change: transform 提前告知浏览器scroll 事件监听,改用 IntersectionObserver,它原生异步且性能友好user-select: none 在可点击区域外——它会让部分安卓设备误判为不可交互,导致 touchstart 不触发backface-visibility: hidden 或 transform: translateZ(0),强制启用 GPU 加速,尤其在低端 Android 设备上效果明显真正难的不是写出第一个摇晃动画,而是让所有微交互在不同设备、不同网络、不同用户偏好(比如开了 prefers-reduced-motion)下都保持一致的节奏和意图。别忘了加媒体查询兜底:@media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; } }。