直接写:target { opacity: 1; } 不会淡入,因为transition需属性值变化触发,而:target仅匹配状态;必须设默认opacity: 0、visibility: hidden,并在:target中改为opacity: 1、visibility: visible,且transition定义在常态规则中。

为什么直接写 :target { opacity: 1; } 不会淡入?
因为 :target 是状态匹配,不是事件监听——它只在 URL 哈希变化后“立刻生效”,而 CSS transition 必须由属性值变化触发。如果弹窗默认就是 opacity: 1,那匹配 :target 时值没变,transition 就不启动。
必须让初始态和 :target 态的 opacity 值不同,且 transition 定义在常态规则里:
- 弹窗容器默认设
opacity: 0; visibility: hidden; - 同时写
transition: opacity 0.3s ease, visibility 0.3s step-end;(注意:visibility 用step-end防止淡出末尾闪一下) -
#modal:target { opacity: 1; visibility: visible; }—— 这才是触发过渡的“变化”
:target 弹窗必须配 position: fixed 吗?
强烈建议配,原因很实际:
- 不设
position: fixed或absolute,弹窗仍参与文档流,:target匹配后可能把下方内容往下顶,造成页面抖动 - 移动端 Safari 在哈希跳转后若页面已滚动,
:target样式有时延迟重绘,fixed 定位能绕过部分重排问题 - 遮罩层(如全屏
.close)必须position: fixed才能覆盖整个视口,否则滚动后就失效
顺带一提:z-index 要显式设高值(比如 z-index: 1000),别依赖默认堆叠上下文。
点击遮罩关闭弹窗,纯 CSS 能做到吗?
能,但有硬约束:遮罩必须是带 href="#" 的 @#@#@#@#@#@#@#@#@#@0,配合 CSS a.close:target { display: none; } 不行——# 不匹配任何 id,:target 永远不生效
<a href="#close"></a>,再加一个空的 <div id="close"></div>(或复用其他无内容元素),这样哈希变 #close 就能触发 #close:target,从而让弹窗容器失配 :target,回归默认隐藏态pointer-events: none 到遮罩上反而更稳移动端 Safari 淡入卡顿、闪一下,怎么调?
这不是你代码写错了,是渲染机制差异:
- 避免在
:target规则里写transform: scale()或translateY(),iOS Safari 对哈希驱动的 transform 动画支持不稳定 - 改用
top/left+opacity组合,transition 写成transition: opacity 0.25s ease, top 0.25s ease; - 如果弹窗内含文字,加
will-change: opacity;到弹窗容器,提前提示合成层提升 - 最易忽略的一点:确保
<meta name="viewport">里没禁用缩放(如user-scalable=no),某些 iOS 版本下这会干扰哈希变更的重绘调度
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











