直接对 display 或 visibility 做 transition 无动画,因二者不支持插值;应使用 transform + opacity 组合实现丝滑过渡,避免重排且兼容性好。

为什么直接对 display 或 visibility 做 transition 没动画
浮动按钮(如 FAB)展开收起时,常见错误是写 transition: visibility 0.2s 或 transition: all 0.3s,结果点击后按钮瞬间消失/出现,毫无过渡。这是因为 visibility 只有 visible/hidden 两个离散值,不支持插值动画;display 更是完全不可动画,浏览器遇到 display: none ↔ block 切换会直接跳变、中断所有过渡。
用 transform + opacity 是最稳的组合
浮动按钮通常绝对定位,天然适合用 transform 控制位移,配合 opacity 控制显隐。两者都是合成属性(composited),不触发重排,动画丝滑且性能好。
- 初始状态设为
transform: scale(0) translate(0, 0); opacity: 0; - 展开状态设为
transform: scale(1) translate(0, -24px); opacity: 1;(假设向上展开) -
transition只写这两个属性:transition: transform 0.25s cubic-bezier(0.17, 0.67, 0.83, 0.67), opacity 0.25s - 别用
transition: all—— 它会把top/left等布局属性也卷进来,一动就重排
展开项高度不确定?别碰 max-height,改用 transform 位移
浮动按钮展开的菜单项(如分享、收藏等子按钮)高度往往不固定,此时强行用 max-height 过渡极易出错:预设值太小会截断,太大则动画拖沓;scrollHeight 动态读取又得 JS 干预,破坏纯 CSS 方案的简洁性。
- 把每个子按钮默认
position: absolute,用transform: translateY()控制它们从下方“浮上来” - 例如:父容器
.fab-menu设overflow: hidden,子项初始transform: translateY(20px),展开时统一加.open类,子项变为transform: translateY(0) - 这样所有子项动画同步,且无需知道具体高度
- 注意:
transform的起始/结束值必须可计算(不能是百分比或auto)
移动端点击无响应或连点两次?关键在事件绑定和样式穿透
真机测试时,常发现第一次点击没反应,或点一下弹出两个菜单——这和浮动按钮的层叠顺序与事件穿透有关。
- 确保按钮有
cursor: pointer和user-select: none,提升触摸识别率 - 展开菜单的遮罩层(如有)必须设
pointer-events: auto,否则点击会穿透到下层 - 按钮本身加
touch-action: manipulation,禁用双击缩放,减少 300ms 延迟影响 - 如果用了 JS 切换类,务必在点击后立即加
disabled或标记isAnimating,防止快速连点触发多次
真实项目里最容易被忽略的是:展开动画结束后,是否清除了 transform 的残留值? 比如用 scale(0) 收起后,若后续 JS 依赖 getBoundingClientRect() 获取尺寸,可能拿到缩放后的错误值。稳妥做法是收起完成后再用 transform: none 重置,而不是只靠动画结束状态。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











