前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库CSS transition visibility 淡入淡出 延迟挂载
CSS动画与视觉

为什么淡出动画要同时用 opacity 和 visibility?

只用 opacity: 0 让元素变透明,它仍然占位置、能被点击。加上 visibility: hidden 才能让它真正「消失」。但 visibility 是瞬间切换的,如果和 opacity 同步变,元素还没淡完就突然不见了。解决办法是给 visibility 加一个等于淡出时长的 transition-delay。

前端进阶之旅 · 一题精讲更新于 2026.09.29
CSS#动画与视觉#动画
先看核心答案读代码示例
理解线索

淡出三件事

  1. opacity控制视觉上的渐隐,支持平滑过渡
  2. visibility控制元素是否可交互,只有 visible 和 hidden 两个状态
  3. transition-delay让 visibility 的切换等到 opacity 过渡完成后再发生

pointer-events: none 也能阻止点击,但它不阻止键盘焦点,屏幕阅读器仍然能读到元素内容。用 visibility: hidden 更彻底。

核心回答

先记住这个答案

opacity 可以平滑过渡但不会让元素真正消失,visibility 能让元素消失但只会瞬间切换。把两者结合起来,给 visibility 的过渡加一个延迟,就能先让 opacity 从 1 渐变到 0,等动画播完再把 visibility 切成 hidden。淡入时反过来:visibility 立刻变成 visible,然后 opacity 从 0 过渡到 1。

  • opacity: 0 的元素仍然可以被点击
  • visibility 是离散切换,没有中间态
  • 淡出时给 visibility 加延迟,淡入时取消延迟
  • visibility 不触发布局重排

经典写法和时序

这是做 tooltip、下拉菜单、弹窗等组件最常用的纯 CSS 淡入淡出方案。关键在于淡出和淡入的 transition 声明不一样。

tooltip 的淡入淡出CSS
.tooltip {
  /* 隐藏状态 */
  opacity: 0;
  visibility: hidden;
  /* 淡出:opacity 花 0.2s 渐隐,visibility 延迟 0.2s 再切换 */
  transition: opacity 0.2s ease, visibility 0s linear 0.2s;
}

.trigger:hover .tooltip {
  /* 显示状态 */
  opacity: 1;
  visibility: visible;
  /* 淡入:visibility 立刻生效(延迟 0s),opacity 花 0.2s 渐显 */
  transition: opacity 0.2s ease, visibility 0s linear 0s;
}

淡出时的时序:鼠标移开,opacity 开始从 1 过渡到 0(耗时 0.2 秒)。visibility 的 transition-delay 是 0.2 秒,所以它等 opacity 播完才从 visible 切成 hidden。在这 0.2 秒的过渡期间,元素仍然是 visible 的,opacity 动画才能正常显示。 淡入时的时序:鼠标移入,visibility 延迟为 0 秒,立刻变成 visible,然后 opacity 从 0 过渡到 1。

为什么不用 display: none

display: none 会把元素从渲染树中移除。元素不在渲染树里,opacity 的过渡根本不会执行,因为浏览器没有「之前的值」可以作为起始帧。

另外,display 的切换会触发回流(reflow),浏览器要重新计算所有受影响元素的位置和尺寸。visibility: hidden 只是让元素不可见、不可交互,它仍然占据布局空间,不会触发回流。对于频繁显隐的组件(比如快速划过菜单项时的子菜单),visibility 的性能开销小得多。

如果确实不想让隐藏的元素占空间,可以在 visibility: hidden 的基础上加 position: absolute 脱离文档流。

visibility 的特殊过渡行为

visibility 不是数值属性,不能像 opacity 那样被插值。但 CSS 规范对它有特殊处理:在过渡期间,只要起始值或目标值中有一个是 visible,整个过渡期间元素都保持 visible,直到过渡结束的那一帧才切换。

这就是为什么 transition-delay 在 visibility 上这么好用——它不是真的在「过渡」visibility,而是在延迟那个瞬间切换的时刻。理解了这一点,就不会困惑于「visibility 明明不能插值为什么还能写 transition」。

回答前,多想一步

容易答错的地方

淡入淡出用同一条 transition 声明
淡入和淡出时 visibility 的延迟是不一样的。淡出时延迟等于 opacity 的过渡时长,淡入时延迟为 0。如果只写一条,要么淡出时元素提前消失,要么淡入时元素显示会延迟。
以为 opacity: 0 的元素不能被点击
opacity 只影响视觉渲染,不影响交互。opacity: 0 的按钮仍然可以点击、仍然可以获得键盘焦点。不加 visibility: hidden,用户可能误触到看不见的元素。
试着用自己的话回答

面试官还会怎么问?

pointer-events: none 能替代 visibility: hidden 吗?

pointer-events: none 只阻止鼠标事件,键盘仍然能聚焦到元素上,屏幕阅读器也会读到它。visibility: hidden 则同时阻止鼠标、键盘和辅助技术的交互,更彻底。

这套方案和 JS 控制 display 比,哪个好?

纯 CSS 方案不需要 JavaScript,性能更好,代码更简单。但如果隐藏后不想让元素占据 DOM(比如长列表中的虚拟滚动),还是需要 JS 控制挂载和卸载。两者适用场景不同。

淡出结束后怎么触发回调?

CSS 过渡结束时会触发 transitionend 事件。在 JavaScript 里监听这个事件,判断 event.propertyName === 'opacity',就可以在淡出完成后执行清理逻辑,比如移除 DOM 节点。

从一道题,走向一组知识

把知识连起来

动画与视觉

transition 和 animation 怎么选?

淡入淡出是典型的两态切换,用 transition 最合适。需要连续多步动画时才考虑 animation。

Flex 布局

flex 容器里放一个绝对定位的子元素,布局会怎样?

弹出层通常用绝对定位脱离文档流,配合 opacity 加 visibility 做显隐动画。

参考资料

  • visibility - CSS | MDN

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 经典写法和时序
  3. 为什么不用 display: none
  4. visibility 的特殊过渡行为
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑