首页 > 编程笔记

CSS :enabled和:disabled的用法

:enabled 伪类和 :disabled 伪类从 IE9 浏览器就已经开始支持,可以放心使用。

由于在实际项目中 :disabled 伪类用得较多,因此我们先介绍 :disabled 伪类。

:disabled的基本用法

最简单的用法是实现禁用状态的输入框,HTML 代码如下:
<input disabled>
此时,我们就可以使用 :disabled 伪类设置输入框的样式。例如,设置背景色为浅灰色:
:disabled {
   border: 1px solid lightgray;
   background: #f0f0f3;
}
效果如下图所示。


图 1 输入框处于禁用状态时背景置为浅灰色(使用:disabled伪类实现)

实际上,直接使用属性选择器也能设置禁用状态的输入框的样式,例如:
[disabled] {
   border: 1px solid lightgray;
   background: #f0f0f3;
}
效果是一样的,如图 2 所示。


图 2 输入框处于禁用状态时背景置为浅灰色(使用属性选择器实现)

后一种方法的兼容性更好,IE8 浏览器也支持。

:enabled和:disabled的细节知识

我们需要先搞明白 :enabled 伪类与 :disabled 伪类是否对立。

对于常见的表单元素,:enabled 伪类与 :disabled 伪类确实是对立的,也就是说,如果这两个伪类样式同时设置,有且只有一个伪类样式匹配。

下面以输入框元素为例,CSS 代码如下:
:disabled {
   border: 1px solid lightgray;
   background: #f0f0f3;
}
:enabled {
   border: 1px solid deepskyblue;
   background: lightskyblue;
}

HTML 代码如下:
<input disabled value="禁用">
<input readonly value="只读">
<input value="普通">

readonly(只读)状态也认为是 :enabled,最终效果如下图所示。


图 3 :enabled与:disabled两种样式中必定渲染其一

之前提到过,在 Chrome 浏览器下,:enabled 伪类也可以匹配带有 href 属性的 <a> 元素,这其实是不对的,现在 Chrome 浏览器已经解决了此问题,大家在使用 :enabled 伪类的时候可以无须顾虑 <a> 元素了。

对于 <select> 下拉框元素,无论是 <select> 元素自身,还是其后代 <option> 元素, :enabled 伪类和 :disabled 伪类都能匹配,所有浏览器都支持。

例如有如下 HTML 代码和 CSS 代码:
<select multiple>
  <option>选项1</option>
  <option disabled>选项2</option>
  <option>选项3</option>
  <option>选项4</option>
</select>

option:disabled {
  color: silver;
}
最终的渲染效果如下图所示,可以看到设置了 disabled 属性的 <option> 元素中的文字是银色的。


图 4 :disabled伪类匹配<option>元素

在 IE 浏览器下,:enabled 伪类与 :disabled 伪类并不匹配 <fieldset> 元素,这是有问题的,但其他浏览器没有这个问题。因此,如果使用 <fieldset> 元素一次性禁用所有表单元素,就不能通过 :disabled 伪类识别(如果要兼容IE浏览器),可以使用 fieldset[disabled] 选择器进行匹配。

设置 contenteditable="true" 的元素虽然也有输入特性,但是 :enabled 伪类不能匹配,所有浏览器都不支持。同样,:enabled 伪类也不能匹配设置 tabindex 属性的元素。

设置 visibility:hidden 或者 display:none 的元素依然能够被 :enabled 伪类和 :disabled 伪类匹配。

:enabled和:disabled的实际应用

:enabled 伪类在 CSS 开发中是略显鸡肋的伪类,因为表单元素默认就是 enabled 状态的,不需要额外的 :enabled 伪类匹配。

例如,可以像下面这样做:
.cs-input {
   border: 1px solid lightgray;
   background: white;
}
.cs-input:disabled {
   background: #f0f0f3;
}

而无须多此一举,再写上 :enabled 伪类:
/* :enabled多余 */
.cs-input:enabled {
   border: 1px solid lightgray;
   background: white;
}
.cs-input:disabled {
   background: #f0f0f3;
}
但是 :enabled 伪类在 JavaScript 开发中很有用,因为 JavaScript 没有 CSS 这样的语句覆盖特性,必须精准匹配对应的元素才行。所以,我们要想获取表单中的可用控件元素,只能使用 :enabled 伪类。

例如我们可以使用 document.querySelectorAll ('form :enabled') 查询所有可用表单元素,以实现自定义的表单序列化方法。

至于 :disabled 伪类,最常用的应该就是按钮了。只要你的网页项目不需要兼容旧版本的 IE 浏览器,就可以使用原生的 <button> 按钮实现,这样做的优点非常多。

以按钮禁用为例,点击按钮发送 Ajax 请求是一个异步过程,为了防止重复点击请求,通常的做法是设置标志量。实际上,如果是原生的按钮(无论是 <button> 按钮还是 <input> 按钮),只要设置按钮 disabled = true,点击事件自然就会失效,无须用额外的 JavaScript 代码进行判断,同时语义更明确,而且可以使用 :disabled 伪类精确控制样式。

例如:
<button id="csButton" class="cs-button">删除</button>
/* 按钮处于禁用状态时的样式 */
.cs-button:disabled {}
csButton.addEventListener('click', function () {
   this.disabled = true;
   // 运行ajax
   // ajax完成后设置按钮disabled为false
});
充分利用浏览器内置行为会使代码更简洁,功能更健壮,语义更明确,因此没有不使用它的理由。

由于历史遗留原因,网页中的按钮多使用 <a> 元素。对于禁用状态,很多人会用 pointer- events:none 来控制,虽然用鼠标点击它确实无效,但是按 Tab 键依然可以访问它,按 Enter 键也依然可以触发点击事件,所以用这种方法实现的其实是伪禁用。同时,设置了 pointer-events:none 的元素无法显示 title 提示,可用性反而降低了。因此,尽量使用原生按钮实现交互效果。

推荐阅读

副业交流群 关注微信公众号,加入副业交流群,学习变现经验,交流各种打法。