:target 仅响应原生 hash 导航,React/Vue 中失效主因是框架路由未触发浏览器 hash 更新或 DOM 异步挂载导致匹配失败;需用 window.location.hash 或补 scrollIntoView,并确保 html{scroll-behavior:smooth}。

:target 本身不控制跳转行为,只响应 URL hash 变更;平滑滚动必须靠 scroll-behavior: smooth,且必须写在 html 元素上——写在 body 或其他元素上无效。
为什么 :target 在 React/Vue 里经常不生效
根本不是 CSS 写错了,而是框架路由没真正触发浏览器原生 hash 导航:
- 用
router.push("/path#section2")或history.pushState()后,location.hash没同步更新 →:target不匹配 - 目标元素是异步挂载的(比如
useEffect里才document.getElementById("section2")),hash 已存在但 DOM 还没渲染 → 匹配失败 - ID 值含非法字符(如
id="user.profile"),CSS 中点号需转义,但:target不支持转义写法 → 实际应避开,改用id="user-profile"
怎么让 :target 真正触发 + 平滑滚动
最轻量、兼容性最好的做法是绕过框架路由,直接操作 hash:
- 点击时执行
window.location.hash = "#section2"—— 它会同时触发:target样式 + 自动平滑滚动(前提是html { scroll-behavior: smooth; }) - 如果必须用
pushState,得补一句location.replace("#section2")(避免多一条历史记录),再手动调用document.getElementById("section2")?.scrollIntoView({ behavior: "smooth" })做视觉兜底 - 别指望
useEffect(() => { ... }, [location.hash])能激活:target样式 —— 它只能帮你做 JS 层面的高亮或滚动,不能替代原生 hash 导航
:target 动画和样式容易踩的坑
:target 是瞬时状态,不是事件,没有中间态,所以很多常见写法会失效:
立即学习“前端免费学习笔记(深入)”;
- 别用
display: none+:target { display: block }—— 触发回流、无法过渡、布局抖动 - 别只在
:target里写transition—— 必须提前写在基础选择器里,例如section { transition: opacity 0.3s, transform 0.3s; } - 想加入场动画?用
transform和opacity配合默认隐藏态:section { opacity: 0; transform: translateY(10px); }+section:target { opacity: 1; transform: translateY(0); } - 固定导航栏遮挡?给目标元素加
scroll-margin-top: 64px(数值 ≈ header 高度),不是写在body或html上
真正难调的不是语法,而是动态渲染场景下 hash 和 DOM 的时序错位 —— 如果页面加载时 URL 已带 #faq,但 <div id="faq"></div> 还没挂载,:target 就永远不生效,连补救都得靠 JS 监听并延迟触发。这不是 bug,是规范行为。


















