:read-only伪类仅对原生支持readonly的input(非checkbox/radio/hidden)、textarea生效,不支持div、span、自定义组件及contenteditable元素;IE全系和旧Edge不支持,select行为不一致,需用[readonly]兜底。

:read-only 伪类本身不能直接让元素只读,它只响应已存在 readonly 属性的原生表单控件;用错对象或漏写降级规则,样式根本不会生效。
为什么 :read-only 样式不生效
常见错误是给 <div readonly> 或自定义组件加 :read-only,但浏览器只识别原生支持 readonly 的元素:仅 <input>(type 不为 checkbox/radio/hidden 等)、<textarea>、<select>(部分浏览器支持,但不推荐依赖)。contenteditable="true" 元素即使设了 readonly,也不会匹配 :read-only。
另外,IE 完全不支持 :read-only,旧 Edge(≤17)也有兼容问题——纯靠它写样式等于放弃一部分用户。
- ✅ 正确目标:
input[type="text"]、input[type="email"]、textarea - ❌ 无效目标:
div、span、custom-input、input[type="checkbox"] - ⚠️ 注意:
select的:read-only行为在 Safari 和 Firefox 中不一致,建议统一用[readonly]选择器兜底
input:read-only 和 input[readonly] 怎么选
两者语义不同:[readonly] 是属性选择器,只要 DOM 上有 readonly 属性就匹配;:read-only 是伪类,依赖浏览器对“只读状态”的运行时判断(比如 JS 动态设置 el.readOnly = true 但没调 el.setAttribute('readonly', ''),可能不触发)。
立即学习“前端免费学习笔记(深入)”;
保险做法是双写,且顺序上把 [readonly] 放前面(兼容性优先):
input[readonly], textarea[readonly] {
background-color: #f5f5f5;
color: #666;
border-color: #ddd;
cursor: not-allowed;
}
input:read-only, textarea:read-only {
background-color: #f5f5f5;
color: #666;
border-color: #ddd;
cursor: not-allowed;
}
- 不要写
input[readonly="true"]或input[readonly="readonly"]——readonly是布尔属性,值为空也匹配 - 必须显式包含
textarea,它常被遗漏但同样支持readonly - 加
cursor: not-allowed比单改背景色更能提示用户不可编辑
背景置灰后文字看不清?别用 opacity 或 filter: grayscale()
opacity: 0.6 会让文字、边框、图标全变淡,可读性反而下降;filter: grayscale(100%) 会把背景图、渐变、图标一并灰掉,视觉上像禁用而非只读,还可能干扰父容器的 transform 或导致 Safari 重绘异常。
更可控的做法是分别控制背景、文字、边框颜色:
- 背景用浅灰:
background-color: #f5f5f5 - 文字保持清晰:
color: #666(不是#999或透明度降低) - 边框稍弱化:
border-color: #ddd - 若需保留原背景图,可用
background-blend-mode: multiply叠一层linear-gradient(to bottom, rgba(245,245,245,0.8), rgba(245,245,245,0.8)),但要测试 Chrome/Firefox/Safari 兼容性
Vue/React 中动态 readonly 状态没反应?检查属性是否真写进了 DOM
框架中用 :readonly="isReadonly"(Vue)或 readOnly={isReadonly}(React)渲染后,DOM 上必须真实存在 readonly 属性,否则 :read-only 不会触发。某些场景下属性可能没真正落库:
- Vue 中用了
Object.freeze包裹 data,导致响应式失效 - React 中
shouldComponentUpdate或React.memo阻断了更新,readOnly属性未同步到 DOM - JS 直接操作
el.readOnly = true,但没补el.setAttribute('readonly', '')
遇到这类问题,最稳的 fallback 是改用 class 控制样式,例如:input.is-readonly,再由 JS 动态增删 class,彻底绕过伪类依赖。
复杂点在于:只读状态常和权限、流程阶段耦合,而 CSS 无法感知业务逻辑;一旦出现“该灰没灰”或“不该灰却灰了”,优先查 DOM 是否真有 readonly 属性,而不是怀疑选择器写错了。


















