真正匹配 :read-only 的元素是 <input>(非 hidden 类型)和 <textarea> 中显式声明 readonly HTML 属性的实例;<select>、<button> 不支持,JS 设置 readOnly = true 可能漏样式,disabled 元素完全不匹配。

:read-only 和 :read-write 能区分输入状态,但只对真实写了 readonly 属性的 <input>(非 type="hidden")和 <textarea> 生效;disabled 元素完全不匹配,JS 设置 el.readOnly = true 也不触发样式。
哪些元素真正匹配 :read-only?
浏览器只看 DOM 中是否存在 readonly 这个布尔属性,不关心 JS 是否锁了输入、也不管是否加了 disabled 或 contenteditable="false":
-
<input type="text" readonly>✅ 匹配 -
<textarea readonly>✅ 匹配 -
<input type="number" readonly>✅ 但 Safari ≤15.3 有漏匹配 bug -
<select readonly>❌ 不支持,伪类完全忽略 -
<button readonly>❌ 无效 -
el.setAttribute('readonly', '')✅ 推荐,确保属性写入 DOM -
el.readOnly = true⚠️ 多数浏览器识别,但 SSR 或首屏渲染可能漏样式
:read-write 不等于 “没加 readonly”
:read-write 是浏览器根据真实可编辑能力判定的状态,不是简单否定属性:
-
<input type="text">✅ 默认匹配(无readonly、无disabled、类型支持输入) -
<input type="radio">❌ 不匹配,即使没加readonly -
<input disabled>❌ 既不匹配:read-write,也不匹配:read-only,只走:disabled -
<div contenteditable="true">✅ 能匹配,但 Safari 15.4 前有兼容问题 -
<div contenteditable="false">❌ 规范说该匹配:read-only,但实际多数浏览器不认,得用[contenteditable="false"]
和 :disabled 共存时的样式优先级陷阱
:disabled 的权重天然高于 :read-only,哪怕你把它写在后面,只要元素带 disabled 属性,:disabled 样式一定生效:
立即学习“前端免费学习笔记(深入)”;
- 别让
readonly和disabled同时存在——语义冲突:readonly字段仍可聚焦、可复制、会提交;disabled则彻底禁用 -
:read-only默认允许文本选择,想禁止需显式加user-select: none - 只读输入框仍会接收 Tab 焦点,若查看模式下不想停在这里,得手动设
tabindex="-1" - IE 全系不支持这两个伪类,兜底建议用
input[readonly]+@supports selector(:read-only)包一层覆盖
最常被忽略的是:伪类只响应 HTML 属性,不响应 JS 行为。哪怕你绑了 oninput="return false" 或 preventDefault,只要没写 readonly 属性,:read-only 就不会生效。


















