真正响应 :read-only 的元素仅有 <input>(非 hidden 类型)和 <textarea>,且仅当其 HTML 中存在 readonly 布尔属性时生效;<select>、<button> 等不支持,JS 设置 readOnly 属性无效。

:read-only 和 :read-write 伪类能用,但只对真实写了 readonly 属性的 <input>(非 type="hidden")和 <textarea> 生效;disabled 元素完全不匹配,contenteditable 需单独处理。
哪些元素真正响应 :read-only?
浏览器只看 DOM 中是否存在 readonly 这个布尔属性,不关心 JS 是否禁用了输入逻辑,也不管是否加了 disabled 或 contenteditable="false":
-
<input type="text" readonly>✅ 匹配:read-only -
<textarea readonly>✅ 匹配:read-only -
<input type="number" readonly>✅ 但 Safari ≤15.3 有漏匹配 bug -
<select readonly>❌ 不支持,伪类完全忽略 -
<button readonly>❌ 同样无效 -
el.readOnly = true❌ 不触发,必须用el.setAttribute('readonly', '')或写在 HTML 里
:read-write 不等于 “没加 readonly”
:read-write 表示“当前可编辑状态”,不是简单否定 readonly 属性。它和 input:not([readonly]) 语义不同、行为也不同:
-
<input readonly disabled>→ 不匹配:read-write,也不匹配:read-only(因:disabled优先级更高) -
<input disabled>→ 只匹配:disabled,:read-write和:read-only都不生效 -
<div contenteditable="true">→ 匹配:read-write,但 Safari 15.4 之前有兼容问题 -
<div contenteditable="false">→ 规范说该匹配:read-only,但多数浏览器实际不认,建议用[contenteditable="false"]属性选择器兜底
和 :disabled 共存时的样式优先级陷阱
:disabled 的权重天然高于 :read-only,哪怕你把 :read-only 写在后面,只要元素带 disabled,:disabled 样式一定生效:
立即学习“前端免费学习笔记(深入)”;
-
:read-only元素仍可聚焦、可选中文本、可提交值;:disabled则彻底禁用交互、不提交、不获焦 - 别让
readonly和disabled同时存在——语义冲突:一个是“展示+可复制”,一个是“彻底锁定” - 想让只读输入框灰但还能选中复制?用
:read-only { background: #f5f5f5; color: #666; } - 想让禁用按钮不可点且变灰?必须用
:disabled,:read-only对<button>完全无效
IE 和旧 Safari 的兼容性怎么兜底?
IE 全系不支持这两个伪类,Safari ≤15.3 在 input[type="number"] 上有漏匹配 bug,iOS 14.5 以下需降级处理:
- 简单兜底:用
input[readonly]和input:not([readonly])写两套规则,再用@supports selector(:read-only)包一层覆盖 - JS 检测示例:
if (CSS.supports('selector(:read-only)')) { /* 加载伪类样式 */ } else { document.querySelectorAll('input[readonly]').forEach(el => el.classList.add('is-readonly')) } - 别依赖
:read-only做权限控制——它纯属表现层,用户删掉属性就能绕过
真正容易被忽略的是:伪类只响应 HTML 属性,不响应 JS 状态;contenteditable 的行为和原生表单控件完全不同;而 :disabled 和 :read-only 混用时,视觉表现可能符合预期,但语义和表单行为已经错乱。



















