display: none 无法触发 transition,因浏览器不将其变化纳入动画系统;应拆分视觉(opacity)、交互(visibility)和位置(transform)三维度,配合 transition 和 transitionend 精确控制显隐。

直接写 display: none 切换不会触发过渡动画,必须用 opacity 和 transform 配合 transition,再用 visibility 控制交互穿透——这是唯一能兼顾平滑、可访问、不闪动的方案。
为什么 display + transition 不生效
浏览器对 display 的切换是“立即生效”,它不参与 CSS 动画系统,transition 完全监听不到值的变化过程。你写 display: none → block,元素只会瞬间出现或消失,毫无过渡可言。
- 常见错误:给
.modal { display: none; transition: all 0.3s; },然后 JS 里el.style.display = 'block'—— 动画根本不会跑 - 更糟的是:如果同时设了
opacity: 0却没配visibility,元素虽不可见但仍占位、可聚焦、能响应点击 - 正确思路:把“显隐”拆成两个维度——视觉(
opacity)、交互(visibility)、位置/大小(transform)
transition 实现弹窗入场/退场的标准写法
入场靠 opacity 和 transform 同步变化,退场靠 transitionend 事件清理 visibility,避免闪动。
- CSS 中这样写:
transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.17, 0.67, 0.83, 0.67), visibility 0s linear 0.3s - 初始状态:
opacity: 0; transform: scale(0.9) translateY(20px); visibility: hidden - 激活类(如
.modal.active)中:opacity: 1; transform: scale(1) translateY(0); visibility: visible - 退场时,先移除
.active类,等transitionend触发后再做 DOM 清理或重置逻辑,别在移除类后立刻remove()
移动端 fixed 定位 + transform 居中容易踩的坑
右下角、居中、全屏遮罩这些场景,position: fixed 是底线,但仅靠 top: 50%; left: 50% 不够,必须加 transform: translate(-50%, -50%),否则在 iOS Safari 或安卓 WebView 中会偏移。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
.modal { position: fixed; top: 50%; left: 50%; margin-top: -100px; margin-left: -150px; }——margin在缩放或字体加载时会失准 - 遮罩层(overlay)必须设
inset: 0或top: 0; left: 0; width: 100%; height: 100%,且z-index ≥ 1000,否则会被 sticky 导航栏或 footer 盖住 - 避免对
height或width做transition—— 它们触发布局重排,动画卡顿明显,一律改用transform: scale()
防抖 + 状态锁不是可选项,是必选项
用户手快连点“打开弹窗”按钮,若没锁,可能同时创建多个弹窗实例,DOM 堆叠、焦点错乱、关闭逻辑失效——这在表单类弹窗里尤其致命。
- JS 打开逻辑里第一时间加锁:
button.disabled = true或设标志位isModalOpen = true - 关闭后记得恢复:
button.disabled = false或清标志位,否则按钮永久失活 - 如果弹窗内含异步操作(如 fetch),锁要覆盖整个生命周期,不能只锁点击瞬间
- 别依赖 CSS 类名是否存在来判断状态,要用明确的布尔变量或 DOM dataset(如
data-open="true")
最常被忽略的是 visibility 的延迟切换时机和 transitionend 的事件监听粒度——少写那 0.3s 的 visibility 延迟,就可能在退场动画最后一帧看到内容突然“啪”一下消失。


















