:link 和 :visited 仅支持有限颜色类属性,LVHA 是防止样式覆盖的强制顺序;浏览器为隐私保护屏蔽非颜色属性;无效 href 不触发伪类;突破限制需用 class + JS 手动管理。

直接说结论::link 和 :visited 只能靠颜色类属性做有限区分,所谓“爱恨原则”(LVHA)不是风格偏好,而是防止样式被静默覆盖的硬性顺序要求。
为什么 :visited 设置 background 或 transition 没反应
浏览器主动屏蔽了 :visited 对大多数非颜色属性的渲染——这不是兼容性问题,是隐私保护机制。你写 a:visited { background: #f0f0f0; transition: color .2s; },background 被忽略,transition 也被静默丢弃,只有 color 生效。
- 允许设置的属性极窄:仅
color、background-color、border-color、outline-color、column-rule-color等可继承的颜色值 -
background-image、transform、font-weight、text-shadow全部无效 -
getComputedStyle(document.querySelector('a'), ':visited')在 Chrome/Firefox/Safari 中返回空或默认值,JS 无法读取真实状态
LVHA 顺序不是建议,是避免样式错乱的必要条件
a:link → a:visited → a:hover → a:active 这个顺序一旦打乱,就可能让未访问链接显示成已访问色,或悬停时颜色不切换。
- 如果
a:visited写在a:link前面,且两者都设了color,那么所有链接(无论是否访问过)都会按后声明的a:link规则渲染 - 如果
a:hover写在a:visited前面,而两者颜色不同,鼠标移上去时可能突然变色,但移开后又回退到:visited色——因为:hover的权重没赢过后续的:visited - 不要用
!important强行覆盖顺序,它会让状态逻辑更难调试
href 值无效时 :link/:visited 根本不触发
这两个伪类只对真实 URL 生效。写成 <a href="#">、<a href="javascript:void(0)"> 或空 href="",浏览器不视为可访问链接,:link 和 :visited 都不会匹配。
立即学习“前端免费学习笔记(深入)”;
- 测试时务必用真实路径,比如
href="/article/123"或href="https://example.com" - 单页应用中若用前端路由(如
href="/user/profile"),只要浏览器历史中有该条目,:visited就会生效 -
mailto:、tel:等协议链接通常也不触发:visited
想加背景、动画或自定义状态?别硬刚 :visited
真要突破限制,唯一可靠路径是放弃依赖浏览器历史,改用 class 手动管理状态。
- 监听
click事件,给目标<a>加class="visited" - CSS 写
a.visited { background: #f5f5f5; color: #666; },完全不受浏览器限制 - 配合
localStorage持久化标记,刷新后仍保留状态 - 注意:这种方案无法感知用户在其他标签页或设备上的访问行为,和原生
:visited逻辑不同,需按业务需求权衡
最常被忽略的一点:哪怕你严格写了 LVHA 顺序、用了合法属性,只要页面里混用了 currentColor 或 CSS 变量(比如 color: var(--link-visited)),某些浏览器仍可能降级处理——:visited 的颜色推导必须是静态、确定、不可被 JS 探测的值。


















