button
是平时使用最广泛的一个 HTML 元素了,只要有点击交互的地方都推荐使用这个。但是,仍然有大部分网站使用的还是div
,比如某博,所到之处几乎都是 div
既然是按钮,为什么不直接使用button
呢?这里介绍一下使用 button 的 5 个理由
一、禁用特性
button
支持禁用。这也是表单元素的通性,直接设置disabled
属性可以达到禁用的效果
<button disabled>按钮</button>
而且,这种禁用不仅可以禁用鼠标点击,也会禁用键盘访问,是真正意义上的禁用
如果需要改变禁用用的样式,需要通过:disabled
伪类,而不是disabled
属性
button:disabled{ } /*不推荐*/ button[disabled]{ }
因为有时候 button
被禁用,不一定来源于自身,有可能是因为父级元素,比如fieldset
<fieldset disabled> <button>按钮</button> <button>按钮</button> </fieldset>
可以看到,当fieldset
被禁用时,所包含的表单元素全部都被禁用,这些表单元素本身是没有disabled
属性的,所以要禁用一个按钮,一定要通过:disabled
伪类
另外在 div
中,一般通过 pointer-events: none;
来实现,不过这种只能禁用掉鼠标行为
div.disabled{ pointer-events: none; }
当然对于 div
来说,这个方式已经足够,因为 div
本身也不会被聚焦到
二、盒子模型和居中特性
button
的默认盒子属性是 border-box
,进一步扩展开来,几乎所有表单元素的盒子属性都是 border-box
。
所以,在给按钮设置具体尺寸的时候就不需要再设置这个了
button{ padding: 5px 10px; width: 100%; box-sizing: border-box; /* 不需要 */ }
然后,button
中默认是垂直水平居中的。
介于几乎所有的按钮都是居中的设计,所以,你无需设置任何居中属性就能达到水平垂直居中的效果
button{ width: 100px; height: 100px; text-align: center; /* 不需要 */ line-height: 50px; /* 不需要 */ }
三、键盘访问
button
支持键盘访问。当使用 tab
键进行焦点切换时,会有明显的焦点提示(outline
)。而且在聚焦状态,通过键盘 enter
或者 space
键可以触发按钮的点击事件
(下面是键盘操作,使用 tab
聚焦,然后通过 enter
或者 space
键触发点击)
所以,为了保持键盘访问的可见性,最好不要这么做
button{ outline: 0; /* 最好不要这么做 */ }
默认情况下,这个 outline
只会在键盘聚焦时出现,而鼠标点击聚焦不会出现,如果需要改变聚焦的颜色,可以仅仅改变 outline-color
,这样不会影响浏览器默认的出现时机
button{ outline-color: salmon; }
最好不要改变整个outline
,这样会导致不管是键盘聚焦还是鼠标点击聚焦都会出现 outline
(一般设计都不喜欢鼠标点击有outline
)
/* 最好不要这么做 */ button:focus{ outline: 1px solid salmon; }
如果想完全控制键盘聚焦的样式,可以使用这个伪类:focus-visible
,兼容性略差
button:focus-visible{ outline: 5px solid salmon; }
四、表单特性
button
具备一些表单特性。合理使用这些特性,不需要 js 也能实现很多交互,比如这样一个表单
<form> <label>用户: </label><input name="user" required><br> <label>密码: </label><input name="password" type="password" required><br> <button type="submit">登录</button> <button type="reset">重置</button> </form>
其中,type="submit"
天然支持表单提交,也就是触发 form
的 submit
事件,而且也支持回车登录,这样体验就非常好了,输完用户名密码,可以直接敲击回车登录。
type="reset"
可以执行表单的重置,注意这里是重置,而不是清空,可能理解成还原会更好。然后这个特性之前已经这篇文章中得到了应用:CSS 实现搜索相关交互
如果不使用 button
,你可能需要更多的javascript
来实现类似的功能,而且还有可能出现不为人知的 bug
五、屏幕阅读
button
默认支持屏幕阅读访问。比如使用macOS自带的旁白,在读到一个按钮时,可以很清楚的明白这是一个按钮还有内部的文本
如果是一个 div
,如果想达到这样的效果,可能需要
- 为了使
div
聚焦,需要添加tabindex=0
属性 - 为了使
div
被识别成按钮,需要添加role="button"
属性
有时候还有更极端的情况,直接使用背景图作为按钮,没有文字,还需要以下操作
- 为了使
div
能够被识别内容,需要添加aria-label
属性
<div tabindex="0" role="button" aria-label="登录2">登录</div>
这样屏幕阅读基本就能正常访问了
没错,文章开头的做法就是这样的,再来回顾一下这些茫茫多的属性
既然要这么麻烦,为何不直接用 button
呢?
六、为何不使用button
呢
以下是我个人的一些猜想
button
在各个浏览器的样式表现不一致button
不能包含某些标签或者会导致无效,比如a
标签- 历史原因,以前就用
div
实现了,不想折腾 - 不知道
button
有这么多好用的特性 - 不在乎这些,能实现就行,我的
js
非常强 - 实际项目中不需要键盘访问或者屏幕阅读
- 某些第三方组件库的封装
七、总结和说明
以上从样式和功能上介绍了原生 button
元素的几个特性,同时还猜想了一些没有使用button
的原因,下面总结一下:
button
支持禁用特性,通过:disabled
伪类自定义禁用样式button
默认盒子模型是border-box
button
内默认水平垂直居中button
支持键盘访问,在聚焦状态下可以通过enter
或者space
触发点击事件button
键盘聚焦的outline
可以通过outline-color
修改颜色,也可以通过:focus-visible
自定义键盘聚焦样式button
在表单中支持enter
提交表单button
在表单中有重置功能button
默认支持屏幕阅读
虽然有这么多好用的特性,但是实际开发中还是有很多原因没有使用。不过不管以前如何如何,从现在开始,只要碰到"按钮",第一优先选择button
就可以了,不用做过多修饰,就能在不知不觉中提升用户体验。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发