跳转用 <a>,触发操作用 <button>;<a> 必须有 href 指向可访问资源,<button> 禁止用 onclick="location.href=..." 模拟跳转,否则破坏屏幕阅读器播报、键盘交互和右键菜单功能。

该用 <button> 还是 <a>,不看样式,只看行为意图:跳转选 <a>,触发操作选 <button>。混用会直接导致屏幕阅读器误读、键盘焦点失效、右键菜单缺失。
怎么判断一个元素该跳转还是该触发操作
核心就一条:<a> 必须有 href,且指向一个可访问的资源(如 /about、https://example.com、#section1);<button> 绝对不能靠 onclick="location.href=..." 模拟跳转。
- 用户点击后页面整体切换、URL 改变 → 用
<a href="..."> - 用户点击后弹窗、展开折叠区、复制文本、提交表单、播放/暂停 → 用
<button type="button"> - 表单内“提交”“重置”必须用
<button type="submit">或<button type="reset">,不能用<a>或未声明type的<button>
为什么 <button onclick="location.href=..."> 是硬性禁用写法
它表面能跳转,但破坏了三类基础能力:
- 屏幕阅读器只会读作“按钮”,不会播报目标地址,用户无法预判去哪
- 键盘用户按
Enter可能触发,但按Space不触发(<button>只响应Space,<a>响应两者),行为不一致 - 右键菜单里没有“在新标签页打开”“复制链接地址”等原生能力,
rel="noopener"也加不上
真实项目中,这类写法曾导致视障用户反复点击却无反馈,或在弹窗后意外刷新整个页面。
立即学习“前端免费学习笔记(深入)”;
<button> 和 <a> 的 DOM 与语义差异
浏览器和辅助技术靠标签名和属性自动推断角色,不是靠 CSS 类名或视觉样式:
-
<a href="...">天然带role="link"、支持tabindex、能被document.querySelectorAll('a[href]')精确选取 -
<button>天然带role="button"、默认tabindex="0"、按Space触发、禁用时子元素自动不可交互 -
<div class="btn" onclick="...">什么都没有 —— 不是按钮,不是链接,只是个普通容器,必须手动补role="button"、tabindex="0"、onkeydown监听,漏一项就断链
工程规范里应强制 CI 检查:禁止 <button> 出现在 <a> 内部;禁止 <a> 缺失 href 属性;禁止所有跳转逻辑脱离 href。
样式像按钮但语义是链接,怎么写才合规
用 <a> + CSS 伪装,不是反模式,而是标准解法:
- HTML:
<a href="/dashboard" class="btn">进入控制台</a> - CSS 中用
display: inline-block、padding、background、text-decoration: none实现按钮外观 - 外链加
rel="noopener",新窗口加target="_blank",并用::after提示(如content: " (opens in new tab)") - 若图标+文字组合,确保可见文本足够描述(如“下载 PDF 报告”),不要只靠图标
真正容易被忽略的是:即使你把 <a> 样式做得再像按钮,只要没改语义,所有可访问性链路就天然完整;而任何试图用 JS “修补” <div> 或 <button> 跳转行为的做法,都等于在无障碍地基上搭危房。



















