浏览器禁用非颜色属性以防范历史嗅探攻击,是Chrome、Firefox、Safari等自2010年代中期起统一实施的强制隐私策略;仅color、background-color(纯色)、border-color等极少数颜色属性被允许,且currentColor、带alpha的hsl()等表面合法实则无效;JavaScript完全无法探测:visited状态,el.matches(':visited')恒返回false,getComputedStyle也始终返回未访问值。

浏览器主动禁用非颜色属性,防止历史嗅探攻击
这不是兼容性问题,也不是 CSS 写法 bug,而是 Chrome、Firefox、Safari 等现代浏览器从 2010 年代中期起共同实施的强制隐私保护策略。核心目标是阻止恶意网站通过样式差异反推用户访问历史——比如用 getComputedStyle() 读取 background-image 是否加载、offsetWidth 是否变化、transition 是否触发,就能判断某链接是否被点过。
-
background-image、background(含渐变)、opacity(中间值如0.5)、font-size、display、padding、transform全部被静默丢弃,DevTools 中显示为带删除线的灰字 -
transition只允许写成transition: color .2s;写transition: all或transition: background-color .2s会被整个忽略 - 哪怕加了
!important,只要属性不在白名单里,照样不生效
:visited 白名单属性有哪些?哪些看似合法实则无效?
真正可用的只有极少数颜色相关属性,且有隐含限制:
- ✅ 明确支持:
color、background-color(仅纯色,rgba(0,0,0,0.8)中的透明度被截断为 1)、border-color(及border-top-color等方向变体)、outline-color、text-decoration-color - ❌ 表面像颜色但被禁用:
currentColor(动态值不被允许)、hsl()/hwb()中含 alpha 通道、任何带透明度的颜色函数 - ⚠️ 半支持但高风险:
fill和stroke仅对内联 SVG 元素有效,且不能用于外部引用或<use></use>场景
为什么 JavaScript 完全无法探测 :visited 状态?
浏览器不仅限制样式输出,还彻底封死所有 JS 探测路径——这是同一套防御机制的延伸:
-
el.matches(':visited')在现代 Chrome/Firefox 中恒返回false,该 API 已被废弃 -
getComputedStyle(el).color永远返回未访问状态的值(即a:link的计算结果),无论真实访问与否 - CSS 自定义属性(
--my-var)根本不能在a:visited规则中声明,语法合法但浏览器静默忽略 - 试图用
document.styleSheets注入规则再检测渲染差异?已被侧信道防护机制拦截
本地开发时 :visited 不生效的常见环境陷阱
即使代码完全正确,也可能因运行环境导致 :visited 失效:
立即学习“前端免费学习笔记(深入)”;
- 用
file://协议直接双击打开 HTML 文件 → 大多数浏览器默认禁用 :visited - 链接 href 是
#、javascript:void(0)、空值或tel:/mailto:→ 不构成可记录的历史 URL - 用户处于无痕/隐私模式 → 历史不保存,:visited 永远为空
- SPA 跳转未触发
history.pushState或页面未真正加载完成 → 浏览器未将其计入访问历史 - CSS 被注入到
scopedstyle 或 Shadow DOM 中 → :visited 作用域失效
localStorage 记录 href 后加 class="is-visited"。


















