根本原因是浏览器默认滚动打断css动画,解决关键是html{scroll-behavior:smooth},配合:target+@keyframes实现平滑高亮动画,需注意id合法性、ios兼容性及避免布局属性动画。

点击链接后页面跳转但不平滑滚动
这是 :target 和 CSS 动画配合最常遇到的问题:浏览器默认行为会瞬间跳到锚点,打断动画效果。根本原因在于 :target 状态一触发,浏览器就执行原生滚动,而 CSS 动画还没来得及介入。
解决思路不是“阻止默认”,而是让滚动本身变成可动画的 CSS 行为。关键在 scroll-behavior: smooth —— 它必须设在 html 元素上,设在 body 无效。
-
html { scroll-behavior: smooth; }是必要前提,缺了这句,后续所有:target动画都白搭 - 不要用 JavaScript 覆盖
scrollIntoView或监听hashchange,那会绕过:target的声明式逻辑 - 如果页面已存在 js 滚动控制(比如自定义锚点跳转),需统一收口,否则和
scroll-behavior冲突
:target 元素进入视口时没有高亮或缩放动画
:target 本身只是个状态伪类,它不会自动触发任何视觉变化;你得手动写过渡或动画规则。常见错误是只写了 transition 却没设初始态,或者动画属性不支持过渡(比如 display)。
推荐用 transform + opacity 组合,它们天然支持硬件加速且可过渡:
立即学习“前端免费学习笔记(深入)”;
section:target { animation: highlight 0.4s ease-out; } @keyframes highlight { 0% { transform: scale(0.98); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } }
-
:target不支持transition直接作用于自身(因为状态切换无中间帧),必须用@keyframes - 避免对
height、margin等布局属性做动画,可能触发重排,卡顿明显 - 动画时间别超过 0.5s,否则用户会觉得响应滞后
hash 变化但 :target 样式不生效
最典型的现象是 URL 中 #section2 已出现,但对应 section#section2 没触发 :target 样式。问题往往出在元素 ID 的合法性或唯一性上。
- ID 值不能以数字开头,
<section id="2section"></section>是非法的,:target不会匹配它 - ID 必须全局唯一,重复 ID 会让浏览器无法确定目标,
:target行为不可预测 - 确保元素已渲染完成再触发 hash 变化;服务端渲染(SSR)或框架中动态挂载的节点,若 hash 在挂载前就存在,
:target不会回溯生效 - 部分旧版 safari 对
:target的解析有延迟,可加animation-delay: 0.01s微调兼容性
移动端 Safari 中动画卡顿或失效
iOS Safari 对 :target + @keyframes 的组合支持较弱,尤其在页面有 overflow: hidden 或启用 -webkit-overflow-scrolling: touch 时,动画容易被截断或跳帧。
- 移除父容器上的
transform: translateZ(0)或will-change,它们有时会干扰:target的渲染时机 - 用
transform: translateX(0)强制开启 GPU 加速,比单纯scale更稳 - 避免在
:target规则里写position: fixed或z-index变更,iOS 渲染管线对此类组合异常敏感 - 真机测试必须覆盖 iOS 15–17,iOS 16.4 之后修复了部分
:target动画丢帧问题,但低版本仍需降级处理
真正麻烦的是 hash 和 scroll-behavior 的耦合时机——它不像 JS 那样可控,一旦页面结构或 CSS 层叠顺序稍有变动,动画就可能消失不见。多试几次刷新和前进后退,比盯着代码更容易发现问题在哪。