href="" 会刷新当前页面,等价于点击刷新按钮,在 spa 中导致重载丢状态,表单中可能重复提交;href="#" 滚动至顶部,非无反应,需 preventdefault;空链接应降级为 aria-disabled,禁用语义错误的伪按钮,优先使用根相对路径避免断链。

href="" 到底在刷新谁
浏览器看到 href="" 不会报错,也不会当无效链接忽略,而是把当前页面完整 URL 当作跳转目标——等价于点击“刷新”按钮。这在 SPA 场景下尤其危险:路由没接管时,整个页面重载,状态全丢;在表单提交后误配 href="",可能触发重复提交。
- Chrome 和 Safari 会立即刷新;Firefox 表现略保守,但行为不保证一致
- 本地双击打开 HTML 文件(
file://协议)时,href=""会尝试重新加载该文件,但部分浏览器会因安全策略静默失败 - 如果后端模板渲染时字段为空(如
{{.Link}}未赋值),必须做兜底,不能依赖前端 JS 补救
href="#" 不是占位符,是滚动指令
href="#" 的语义非常明确:跳转到当前页 ID 为空的锚点,即页面顶部。哪怕页面没有 <div id="">,它也会强制滚动归零——这不是“没反应”,而是你没注意到滚动抖动。
<ul>
<li>用它做 JS 触发按钮时,必须配 <code>event.preventDefault(),且确保 JS 加载成功、未被拦截
href="#section" 会滚动失败,且无任何提示真不想跳转,就别用
用 <a href="javascript:void(0)"></a> 或 <a href="#"></a> 模拟按钮,本质是语义错误。这类链接无法键盘聚焦、不被屏幕阅读器识别为可操作控件,SEO 也无价值。
- 纯交互按钮请改用
<button type="button"></button>,样式可完全复刻链接外观 - 需要保留链接语义(比如导航菜单中某项暂不可用),可用
<a href="/coming-soon" aria-disabled="true" tabindex="-1"></a>,既合法又可访问 - 服务端模板中,空链接应主动降级:
{{if .URL}}href="{{.URL}}"{{else}}aria-disabled="true" tabindex="-1"{{end}}
相对路径断链比空 href 更隐蔽
写 href="about.html" 看似没问题,但一旦文件位置变动或部署到子路径(如 https://site.com/blog/),就会 404。而 href="" 至少还能刷出来,这种断链是静默的。
- 优先用根相对路径:
href="/about.html"(从域名起算) - 避免
./或../开头的路径,除非你 100% 控制文件组织结构 - 本地开发双击打开时,
/开头路径会指向系统盘根目录(如C:\about.html),此时必须切到本地服务器(如python -m http.server)才能验证真实行为
# 都有明确行为,不是“没写好”,而是“写得太实”。真正难处理的是那些看似正常、却因路径解析规则或运行环境差异而失效的链接——它们不会报错,只在特定路径、特定部署方式下突然失联。











