不可行,因div无语义、不响应键盘操作、屏幕阅读器识别为静态文本而非按钮、表单验证失效、移动端交互丢失;button原生支持聚焦、enter/space触发、role声明、表单提交等完整无障碍能力。

能当按钮用,但不该当按钮用——除非你愿意手动补全所有浏览器原生 button 已经提供的能力。
为什么 div 点击后“看起来”像按钮,其实不是
它只是个空容器,没有语义、不响应键盘、不能被屏幕阅读器识别为可操作控件。用户用 Tab 键导航时会直接跳过它;视障用户听到的是一段普通文本,而不是“按钮,关闭弹窗”;搜索引擎也只把它当作一个布局块,而非交互入口。
常见错误现象:
- 点击
div按钮时,按回车或空格没反应 - 用键盘 Tab 切换焦点,焦点停在上一个输入框后直接跳到下一个链接
- 用 VoiceOver 或 NVDA 测试时,读出来的是“关闭”,而不是“关闭按钮”
button 的默认行为到底省了你哪些事
浏览器给 button 预置了一整套无障碍基础能力,不是“加点样式就行”的问题:
- 自动获得
tabindex="0",天然可聚焦 - 监听
Enter和Space键并触发click事件(注意:Space是按下+释放才触发,不是按下就触发) - 默认有
role="button",无需手动声明 - 在表单内时,
type="submit"会自动触发表单提交(哪怕没写 JS) - 支持
:focus-visible和:active伪类,且行为跨浏览器一致
如果你非要用 div,就得自己手写这些逻辑——而且每次都要重写,不能复用。
什么情况下真得用 div + JS 模拟按钮
极少数场景下,button 的默认行为确实构成干扰,比如:
- 需要完全接管点击区域(例如整个卡片都可点,但语义上不是按钮,而是“跳转到详情页”——这时该用
a,不是div) - 组件库内部封装,要透传
asChild或渲染为不同宿主元素(如 Radix UI 的Button支持asChild渲染为div,但前提是它已注入完整可访问性属性) - 遗留系统中无法修改 HTML 结构,只能靠 JS 注入行为(此时必须补全
role="button"、tabindex="0"、onkeydown处理 Enter/Space)
注意:div 当按钮 ≠ 自定义样式自由。现代 CSS 完全能覆盖 button 默认样式(包括边框、背景、字体、甚至伪元素),不需要牺牲语义换“好看”。
最容易被忽略的兼容细节
就算你写了 role="button" 和 tabindex="0",漏掉下面任何一项,可访问性就断链:
- 没处理
Space键的按下+释放周期(只监听keydown不够) - 没加
cursor: pointer,视觉反馈缺失,鼠标用户不确定是否可点 - 用了
all: unset却忘了重设user-select: none,导致双击选中文本 - 在表单里用了无
type的button,结果点了就刷新页面(默认是type="submit")
真实项目里,95% 的“必须用 div 做按钮”需求,其实只是没查清 button 的 CSS 可定制边界,或者没意识到键盘交互不是锦上添花,而是底线要求。










