你以为完美的按钮,其实是个大bug

你以为完美的按钮,其实是个大bug

七月 04, 2026 semantic-html web-development accessibility frontend best-practices

为什么你的按钮总是出bug?

每个前端开发者都经历过这个。

产品经理甩过来一张设计稿,上面是一个"特别"的按钮。要渐变色,要 hover 动效,按下去还要有反馈。设计师追求完美,这很正常。

于是你二话不说拉了个 <div>,配上 class="btn" 和一堆 CSS。预览效果,完美。设计师点头,通过。

然后用户开始用了——

有人用 Tab 键导航,发现按钮根本进不去焦点顺序。有人按空格键提交表单,没反应。有人开着屏幕阅读器,压根不知道这是个可以点的按钮。

你开始疯狂打补丁:加 click 事件、加 focus 样式、加键盘监听、加上 role="button"tabindex="0"……

最后你写了两百行 JavaScript,就为了模拟一个浏览器天然就能给你的东西。

这就是"技术债"的利息。你当初选错了元素,每一行 workaround 都是你欠下的债。

原生元素的好处,没人告诉你

<button> 这个标签看起来平平无奇,但它背后是一整套交互协议。

用真正的 button:

  • 键盘交互:回车、空格键按预期工作
  • 焦点管理:自然进入 Tab 顺序,还能被 JavaScript 主动 focus
  • 禁用状态:自动阻止所有交互,自动从焦点链移除,屏幕阅读器会播报"已禁用"
  • 表单联动:能提交表单、参与表单验证、响应 form.reset()
  • 无障碍语义:读屏软件直接识别为按钮,不需要额外 ARIA
  • 平台一致:用户知道按钮怎么用,因为所有网站按钮都长一个样

用一个 div + CSS 模拟的按钮呢?

只有你的 CSS。剩下全是活儿。

而且说实话,不管你多仔细,你的实现永远比不上浏览器内置的方案。浏览器背后有专业团队在优化各种边界情况、各种无障碍场景。你的自定义按钮,只有你自己。

真正的问题不是"能不能样式化"

很多开发者的误解在于:以为用语义化 HTML 就意味着接受浏览器丑丑的默认样式。

完全不是一回事。

问题从来不是"能不能自定义外观"。当然可以——加 appearance: none 就能抹掉所有默认样式。渐变、阴影、动画、特殊字体,随便加。浏览器根本不管你长什么样。

问题应该是:"原生功能里,哪些需要保留?"

<button> 可以变成任何你想要的视觉形态,但它的交互能力还在。

而用 div 模拟的话,每一样都要你自己写。没有捷径。

所以,想清楚你要把工程时间花在哪里。花在真正让产品与众不同的地方,而不是重新发明轮子。

你的用户在真实的世界里

设计稿是静态的,但用户不是。

  • 有人在用 Tab 切焦点,手没离开键盘
  • 有人在用语音控制
  • 有人把页面放大到 300% 才能看清
  • 有人用 Safari,有人用 Firefox,有人用 IE(虽然快没了)
  • 有人开着读屏软件

原生 HTML 元素天然就适配这些场景。语义化元素天生可访问,天生支持键盘导航,天生跨平台兼容。

你选择对抗这套基础设施,不只是给自己找麻烦——你做出来的东西,会在某些用户那里以各种奇怪的方式出问题。

下次想用 <div role="button"> 的时候,问自己两个问题:

  1. 我是不是真的需要一个自定义实现?
  2. 还是我只是不喜欢 <button> 这个标签?

答案往往是后者。

用最朴素的方式解决问题,这不是偷懒。浏览器替你把事情做对了,这是功能,不是限制。

语义化不是为了遵守规则。是把对的东西用在对的场景上,然后把你的精力花在真正重要的地方。

Read in other languages:

EL CS UZ TR SV FI RO PT PL NB NL HU IT FR ES DE DA EN