Menu

HTML 按钮:类型、提交、禁用状态与样式

如何用 <button> 元素在 HTML 中创建按钮:三种类型(submit、button、reset)、随表单发送值、禁用按钮、图标按钮,以及保留焦点环的 CSS 样式。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

如何在 HTML 中创建按钮

按钮就是 <button> 元素。标签之间的内容是用户看到的文字,type="button" 表示它运行你的脚本,而不是提交表单。在预览中点击它:

一个能用的按钮只需要这些:文字、type,以及监听 click 的代码。浏览器会让它可以通过键盘聚焦,并且按 Enter 或空格键就能激活,所以键盘用户无需额外处理就能使用。带点击处理函数的 <div> 则什么都没有。

你也可能见过直接写在标签里的 onclick="..."。它能用,但 addEventListener 让脚本和标记分离,还能让多个监听器共用一个按钮。

三种按钮类型

type 属性决定按钮被按下时做什么。

type作用用途
submit提交它所属的表单。这是默认值。表单的主要操作
button本身什么都不做,由你的 JavaScript 决定开关、对话框、计数器,以及任何由脚本控制的功能
reset把表单的每个字段恢复为初始值很少用;用户容易误点

先输入一些内容,再逐个试试这些按钮。表单提交时预览不会离开页面,而是显示表单将要发送的数据。

Reset 恢复的是 HTML 中写好的值(Ada),而不是清空字段。如果你把 Uppercase 按钮上的 type="button" 删掉,它就变成了提交按钮:先把名字转成大写,然后提交表单。

HTML 提交按钮:发送 name 和 value

提交按钮可以带有自己的 name 和 value。只有当这个按钮是触发提交的那个按钮时,它们才会随表单发送,所以两个按钮可以共用一个表单,并告诉服务器选择的是哪个操作:

点击 Publish,表单会发送 title=My first post 和 action=publish。清空标题后再点任意一个按钮:required 会阻止提交,浏览器会显示它自己的提示。在文本框里按 Enter 也会提交,浏览器会把它当作按下了第一个提交按钮,所以发送的是 action=draft。

提交按钮还支持一些只对这个按钮生效、覆盖表单设置的属性:formaction(不同的 URL)、formmethod、formtarget,以及跳过验证的 formnovalidate。对于在必填字段还空着时也应该能用的“保存草稿”按钮,通常会选择 formnovalidate。

放在表单外面的按钮也可以通过 form 属性提交它,属性值是表单的 id:<button type="submit" form="signup">Sign up</button>。

禁用按钮

disabled 属性会关闭按钮。禁用的按钮不响应点击,按 Tab 时会被跳过,也不会随表单发送。浏览器还会把它显示成灰色。一种常见做法是在满足某个条件之前,一直让提交按钮保持禁用:

在 JavaScript 中,button.disabled 是一个布尔属性:把它设为 true 或 false。在 HTML 中,起作用的是这个属性是否存在,所以 disabled="false" 仍然会禁用按钮。

禁用的按钮不会说明自己为什么被禁用,用 Tab 键浏览的键盘用户和屏幕阅读器用户也永远不会停在它上面。如果原因并不明显,就在按钮旁边用文字说明,或者让按钮保持可用,在点击时显示错误提示。

用 CSS 设置按钮样式

浏览器会用自己的字体、边框和背景来绘制按钮。设置几个属性就能把这些全部替换掉。记得保留可见的焦点样式:键盘用户要靠它知道自己在哪里。

每条规则的作用:

  • font: inherit 让按钮使用页面的字体。没有它,按钮会使用浏览器自带的较小的表单字体(Chrome 和 Firefox 中为 13.33px)。
  • cursor: pointer 显示手形光标。按钮默认显示的是普通箭头。
  • :hover、:active 和 :focus-visible 分别设置鼠标悬停、按下和键盘聚焦时的样式。:focus-visible 只在键盘聚焦时显示焦点环,鼠标点击后不会显示,所以你不必为了避免它而去掉 outline。
  • :disabled 选中带有 disabled 属性的按钮。

在预览中按 Tab 键,可以看到琥珀色的焦点环在前两个按钮之间移动,禁用的那个会被跳过。(在 Mac 上,Safari 和 Firefox 只有在系统设置中开启键盘导航后,才会用 Tab 键聚焦到按钮;在 Safari 中,不开启也可以用 Option+Tab。)完整的状态列表请参阅 CSS hover。

带图标的按钮

因为 <button> 可以包含 HTML,所以图标可以放在里面,和文字并排。只有图标的按钮没有可供屏幕阅读器播报的文字,所以要给它加上 aria-label:

SVG 上的 aria-hidden="true" 把它排除在无障碍树之外,所以第一个按钮会被播报为“Add item,按钮”,第二个为“Delete,按钮”。

button 与 input type="submit"

<input type="submit"> 是编写提交按钮的旧方式。两者提交表单的方式完全相同,区别在于它们能包含什么内容。

<input type="submit" value="Send">   <!-- label comes from value, text only -->
<button type="submit">Send</button>  <!-- label is the content, HTML allowed -->
<button><input type="submit">
按钮文字标签之间的内容value 属性
能否包含图标或标记能不能
结束标签必须有没有(空元素)
默认类型submit始终是 submit

请使用 <button>。保留 <input type="submit"> 的唯一理由,是已有的 CSS 或 JavaScript 会选中它。另外还有 <input type="button"> 和 <input type="reset">,对应另外两种类型,原理相同。

按钮还是链接?

按钮在当前页面上执行操作:提交、打开、切换、删除。链接则跳转到另一个 URL。如果点击后地址栏会改变,它就应该是 <a href>,设计需要的话可以设置成按钮的样式。这种做法,以及为什么链接里套按钮是不合法的,请参阅 HTML 按钮链接。

无障碍

  • 使用真正的 <button>。它可以聚焦,支持 Enter 和空格键,并会被播报为按钮。在 <div> 上重新实现这些需要 role、tabindex 和按键处理函数,而且通常还是不完整。
  • 每个按钮都需要一个名称:它的文字,或者只有图标时的 aria-label。
  • 保留可见的焦点样式。只写 outline: none 而不提供替代样式,会让键盘用户迷失方向。
  • 让点击区域足够大。WCAG 2.2 要求至少 24 × 24 个 CSS 像素;像上面样式示例那样的内边距,能让高度达到大约 40 像素。
  • 对于开关按钮,加上 aria-pressed="true" 或 "false",并在状态改变时更新它。

常见错误

  • 表单里的按钮没有写 type。 它会提交表单。所有不用于提交的按钮都要写上 type="button"。
  • 把按钮包在链接里,例如 <a href="/x"><button>Go</button></a>。这是不合法的 HTML,在不同浏览器中的表现也不一样。只用一个元素:设置成按钮样式的链接。
  • 把 <div onclick> 当作按钮。 用键盘无法访问它。
  • 去掉焦点轮廓,却没有添加 :focus-visible 样式。
  • 写 disabled="false",以为按钮是可用的。应该删掉这个属性。
  • 忘了写 font: inherit,然后奇怪为什么按钮的字体和页面其他部分不一样。

常见问题

如何在 HTML 中创建按钮?

写 <button type="button">Click me</button>。标签之间的文字就是按钮上显示的文字。在 JavaScript 中添加 click 监听器让它执行操作,或者把它放进 <form> 并设置 type="submit" 来提交表单。

HTML 按钮的默认类型是什么?

submit。在表单里,没有 type 属性的 <button> 被点击时会提交这个表单,这就是表单里的普通按钮可能会刷新页面的原因。凡是用来运行 JavaScript 的按钮,都要写上 type="button"。

button 和 input type=submit 有什么区别?

两者都能提交表单。<button> 的标签之间可以包含 HTML(图标、粗体文字),而 <input type="submit"> 的文字来自 value 属性,只能是纯文本。现在的代码大多使用 <button>。

如何在 HTML 中禁用按钮?

加上 disabled 属性:<button disabled>Save</button>。禁用的按钮无法点击,也无法获得焦点,它的 name 和 value 也不会随表单发送。删掉这个属性(在 JavaScript 中写 btn.disabled = false)就能重新启用它。

如何让 HTML 按钮跳转到另一个页面?

使用设置成按钮样式的链接:<a href="/pricing" class="btn">See pricing</a>。<button> 用于当前页面上的操作。把按钮包在 <a> 里是不合法的 HTML。

为什么我的按钮会刷新页面?

它在 <form> 里面又没有 type,所以它是一个提交按钮,浏览器会发送表单并加载响应。给它加上 type="button",或者如果你用 JavaScript 处理表单,就在 submit 监听器里调用 event.preventDefault()。

Coddy 编程语言插图

和 Coddy 一起学编程

开始