UI 状态伪类选择器

CSS3 的 UI 状态伪类选择器专门用于选择基于用户界面状态的元素,特别是表单元素。这些选择器让我们能够根据元素的启用、禁用、选中、有效、无效等状态来应用不同的样式,大大增强了表单的用户体验和可访问性。

UI 状态伪类概述

UI 状态伪类选择器基于元素的当前状态来选择元素,这些状态通常由用户交互或元素属性决定。这些选择器在表单验证、用户反馈、状态指示等方面非常有用。

主要 UI 状态伪类

  • :enabled - 启用的元素
  • :disabled - 禁用的元素
  • :checked - 选中的复选框或单选按钮
  • :indeterminate - 不确定状态的复选框
  • :default - 默认选中的元素
  • :valid - 有效的表单元素
  • :invalid - 无效的表单元素
  • :required - 必填的表单元素
  • :optional - 可选的表单元素
  • :in-range - 值在范围内的输入
  • :out-of-range - 值超出范围的输入
  • :read-only - 只读的表单元素
  • :read-write - 可编辑的表单元素

启用和禁用状态

:enabled

选择启用的表单元素,即没有 disabled 属性的元素。

/* 启用的输入框 */
input:enabled {
  background: white;
  border: 1px solid #ced4da;
  cursor: text;
}

input:enabled:hover {
  border-color: #007bff;
}

input:enabled:focus {
  border-color: #007bff;
  box-shadow: 0 0 0 3px rgba(0,123,255,0.25);
}

:disabled

选择禁用的表单元素,即具有 disabled 属性的元素。

/* 禁用的输入框 */
input:disabled {
  background: #f8f9fa;
  border: 1px solid #dee2e6;
  color: #6c757d;
  cursor: not-allowed;
}

input:disabled::placeholder {
  color: #adb5bd;
}

/* 禁用的按钮 */
button:disabled {
  background: #e9ecef;
  color: #adb5bd;
  cursor: not-allowed;
  opacity: 0.6;
}

实际应用:

/* 表单组样式 */
.form-group {
  position: relative;
  margin-bottom: 20px;
}

.form-group input:enabled + label {
  color: #333;
}

.form-group input:disabled + label {
  color: #6c757d;
}

/* 禁用状态提示 */
.disabled-field {
  position: relative;
}

.disabled-field:disabled::after {
  content: "(已禁用)";
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #6c757d;
  font-size: 12px;
}

选中状态

:checked

选择选中的复选框、单选按钮或选项。

/* 选中的复选框 */
input[type="checkbox"]:checked {
  accent-color: #007bff;
}

input[type="checkbox"]:checked + label {
  color: #007bff;
  font-weight: bold;
}

/* 选中的单选按钮 */
input[type="radio"]:checked {
  accent-color: #007bff;
}

input[type="radio"]:checked + label {
  color: #007bff;
}

/* 自定义复选框样式 */
.custom-checkbox input:checked + .checkmark {
  background: #007bff;
  border-color: #007bff;
}

.custom-checkbox input:checked + .checkmark::after {
  display: block;
}

实际应用:

/* 任务列表样式 */
.task-item {
  display: flex;
  align-items: center;
  padding: 10px;
  border-bottom: 1px solid #eee;
}

.task-item input:checked + .task-text {
  text-decoration: line-through;
  color: #6c757d;
}

/* 同意条款复选框 */
.terms-checkbox input:checked + label {
  color: #28a745;
}

.terms-checkbox input:checked + label::before {
  content: "✓ ";
  color: #28a745;
}

:indeterminate

选择处于不确定状态的复选框。

/* 不确定状态的复选框 */
input[type="checkbox"]:indeterminate {
  accent-color: #ffc107;
}

input[type="checkbox"]:indeterminate + label {
  color: #ffc107;
}

实际应用:

/* 全选复选框不确定状态 */
.select-all-checkbox:indeterminate + label::after {
  content: "(部分选中)";
  color: #ffc107;
}

/* 树形菜单不确定状态 */
.tree-node:indeterminate + .node-label {
  color: #ffc107;
}

表单验证状态

:valid

选择通过验证的表单元素。

/* 有效的输入框 */
input:valid {
  border-color: #28a745;
}

input:valid:focus {
  box-shadow: 0 0 0 3px rgba(40, 167, 69, 0.25);
}

/* 有效状态图标 */
.valid-input:valid::after {
  content: "✓";
  color: #28a745;
  margin-left: 5px;
}

:invalid

选择未通过验证的表单元素。

/* 无效的输入框 */
input:invalid {
  border-color: #dc3545;
}

input:invalid:focus {
  box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.25);
}

/* 无效状态图标 */
.invalid-input:invalid::after {
  content: "✗";
  color: #dc3545;
  margin-left: 5px;
}

实际应用:

/* 表单验证样式 */
.form-control {
  padding: 10px 15px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 16px;
  transition: all 0.3s ease;
}

.form-control:valid:not(:placeholder-shown) {
  border-color: #28a745;
  background: url('valid-icon.png') no-repeat right 10px center;
}

.form-control:invalid:not(:placeholder-shown) {
  border-color: #dc3545;
  background: url('invalid-icon.png') no-repeat right 10px center;
}

/* 验证消息 */
.error-message {
  display: none;
  color: #dc3545;
  font-size: 14px;
  margin-top: 5px;
}

.form-control:invalid:not(:placeholder-shown) + .error-message {
  display: block;
}

必填和可选状态

:required

选择具有 required 属性的必填表单元素。

/* 必填字段 */
input:required,
textarea:required,
select:required {
  border-left: 3px solid #dc3545;
}

input:required::placeholder,
textarea:required::placeholder {
  color: #dc3545;
}

input:required::placeholder::before {
  content: "* ";
}

/* 必填字段标签 */
.required-field::after {
  content: " *";
  color: #dc3545;
}

:optional

选择不具有 required 属性的可选表单元素。

/* 可选字段 */
input:optional,
textarea:optional {
  border-left: 3px solid #6c757d;
}

input:optional::placeholder {
  color: #6c757d;
}

实际应用:

/* 表单字段样式 */
.form-field {
  position: relative;
  margin-bottom: 20px;
}

.form-field input:required {
  padding-left: 15px;
}

.form-field input:optional {
  padding-left: 15px;
}

/* 必填字段提示 */
.required-hint {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #dc3545;
  font-size: 12px;
}

范围状态

:in-range

选择值在指定范围内的输入元素。

/* 范围内的输入 */
input:in-range {
  border-color: #28a745;
}

input:in-range:focus {
  box-shadow: 0 0 0 3px rgba(40, 167, 69, 0.25);
}

:out-of-range

选择值超出指定范围的输入元素。

/* 超出范围的输入 */
input:out-of-range {
  border-color: #dc3545;
}

input:out-of-range:focus {
  box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.25);
}

实际应用:

/* 年龄输入框 */
.age-input {
  width: 100px;
  padding: 10px;
  border: 1px solid #ced4da;
  border-radius: 4px;
}

.age-input:in-range {
  border-color: #28a745;
}

.age-input:out-of-range {
  border-color: #dc3545;
}

/* 范围提示 */
.range-hint {
  display: none;
  color: #dc3545;
  font-size: 12px;
  margin-top: 5px;
}

.age-input:out-of-range + .range-hint {
  display: block;
}

只读和可编辑状态

:read-only

选择只读的表单元素。

/* 只读输入框 */
input:read-only {
  background: #f8f9fa;
  border: 1px solid #dee2e6;
  color: #6c757d;
  cursor: default;
}

input:read-only:focus {
  outline: none;
}

/* 只读文本域 */
textarea:read-only {
  background: #f8f9fa;
  border: 1px solid #dee2e6;
  color: #6c757d;
  resize: none;
}

:read-write

选择可编辑的表单元素。

/* 可编辑输入框 */
input:read-write {
  background: white;
  border: 1px solid #ced4da;
  cursor: text;
}

input:read-write:hover {
  border-color: #007bff;
}

input:read-write:focus {
  border-color: #007bff;
  box-shadow: 0 0 0 3px rgba(0,123,255,0.25);
}

实际应用:

/* 用户信息表单 */
.user-info input:read-only {
  background: #f8f9fa;
  color: #6c757d;
  cursor: not-allowed;
}

.user-info input:read-write {
  background: white;
  color: #333;
  cursor: text;
}

/* 只读标识 */
.read-only-indicator {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #6c757d;
  font-size: 12px;
}

input:read-only + .read-only-indicator::after {
  content: "(只读)";
}

默认状态

:default

选择默认选中的表单元素。

/* 默认选中的单选按钮 */
input[type="radio"]:default:checked {
  accent-color: #007bff;
}

input[type="radio"]:default:checked + label {
  color: #007bff;
  font-weight: bold;
}

/* 默认选中的选项 */
option:default {
  background: #e3f2fd;
  font-weight: bold;
}

实际应用:

/* 默认选项标识 */
.default-option {
  position: relative;
}

.default-option:default::after {
  content: "(默认)";
  color: #007bff;
  font-size: 12px;
  margin-left: 5px;
}

/* 默认按钮 */
button:default {
  background: #007bff;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
}

button:default:hover {
  background: #0056b3;
}

综合应用示例

1. 完整表单样式

/* 表单容器 */
.form-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 30px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* 表单控件 */
.form-control {
  width: 100%;
  padding: 12px 15px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 16px;
  transition: all 0.3s ease;
}

/* 启用状态 */
.form-control:enabled {
  background: white;
}

.form-control:enabled:hover {
  border-color: #007bff;
}

.form-control:enabled:focus {
  border-color: #007bff;
  box-shadow: 0 0 0 3px rgba(0,123,255,0.25);
  outline: none;
}

/* 禁用状态 */
.form-control:disabled {
  background: #f8f9fa;
  border-color: #dee2e6;
  color: #6c757d;
  cursor: not-allowed;
}

/* 必填字段 */
.form-control:required {
  border-left: 3px solid #dc3545;
}

.form-control:required::placeholder {
  color: #dc3545;
}

/* 验证状态 */
.form-control:valid:not(:placeholder-shown) {
  border-color: #28a745;
}

.form-control:invalid:not(:placeholder-shown) {
  border-color: #dc3545;
}

/* 范围状态 */
.form-control:in-range {
  border-color: #28a745;
}

.form-control:out-of-range {
  border-color: #dc3545;
}

/* 只读状态 */
.form-control:read-only {
  background: #f8f9fa;
  color: #6c757d;
  cursor: default;
}

/* 可编辑状态 */
.form-control:read-write {
  background: white;
  color: #333;
  cursor: text;
}

/* 复选框样式 */
.checkbox-wrapper {
  display: flex;
  align-items: center;
  margin-bottom: 15px;
}

.checkbox-wrapper input[type="checkbox"] {
  margin-right: 10px;
}

.checkbox-wrapper input:checked + label {
  color: #007bff;
  font-weight: bold;
}

/* 按钮样式 */
.button {
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
  font-size: 16px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.button:enabled {
  background: #007bff;
  color: white;
}

.button:enabled:hover {
  background: #0056b3;
}

.button:disabled {
  background: #e9ecef;
  color: #adb5bd;
  cursor: not-allowed;
}

2. 动态表单验证

/* 动态验证样式 */
.dynamic-form {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.dynamic-form .form-group {
  position: relative;
  margin-bottom: 20px;
}

.dynamic-form input {
  width: 100%;
  padding: 12px 15px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  font-size: 16px;
}

/* 验证状态 */
.dynamic-form input:valid:not(:placeholder-shown) {
  border-color: #28a745;
}

.dynamic-form input:invalid:not(:placeholder-shown) {
  border-color: #dc3545;
}

/* 验证图标 */
.dynamic-form .form-group::after {
  content: '';
  position: absolute;
  right: 15px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 20px;
}

.dynamic-form input:valid:not(:placeholder-shown) + ::after {
  content: '✓';
  color: #28a745;
}

.dynamic-form input:invalid:not(:placeholder-shown) + ::after {
  content: '✗';
  color: #dc3545;
}

/* 验证消息 */
.validation-message {
  display: none;
  color: #dc3545;
  font-size: 14px;
  margin-top: 5px;
}

.dynamic-form input:invalid:not(:placeholder-shown) ~ .validation-message {
  display: block;
}

浏览器兼容性

UI 状态伪类选择器在所有现代浏览器中都有良好的支持:

  • Chrome 4+
  • Firefox 3.5+
  • Safari 3.2+
  • Edge 所有版本
  • IE 9+

最佳实践

1. 提供清晰的视觉反馈

/* 推荐 - 清晰的视觉反馈 */
input:valid {
  border-color: #28a745;
  box-shadow: 0 0 0 3px rgba(40, 167, 69, 0.25);
}

/* 不推荐 - 视觉反馈不明显 */
input:valid {
  border-color: #28a745;
}

2. 结合其他选择器使用

/* 推荐 - 结合其他选择器 */
input[type="email"]:valid:not(:placeholder-shown) {
  border-color: #28a745;
}

/* 不推荐 - 选择器过于宽泛 */
input:valid {
  border-color: #28a745;
}

3. 考虑可访问性

/* 推荐 - 考虑可访问性 */
input:focus {
  outline: 2px solid #007bff;
  outline-offset: 2px;
}

/* 不推荐 - 移除焦点样式 */
input:focus {
  outline: none;
}

总结

CSS3 的 UI 状态伪类选择器为表单样式提供了强大的控制能力:

主要分类:

  • 启用/禁用状态::enabled:disabled
  • 选中状态::checked:indeterminate
  • 验证状态::valid:invalid
  • 必填/可选状态::required:optional
  • 范围状态::in-range:out-of-range
  • 只读/可编辑状态::read-only:read-write
  • 默认状态::default

实际应用:

  • 表单验证样式
  • 用户状态反馈
  • 动态表单交互
  • 可访问性增强
  • 用户体验优化

最佳实践:

  • 提供清晰的视觉反馈
  • 结合其他选择器使用
  • 考虑可访问性
  • 保持样式一致性
  • 优化用户体验

掌握这些 UI 状态伪类选择器,能够让我们创建更加智能、用户友好的表单界面,大大提升用户体验。