:read-only仅对含readonly布尔属性的<input>(非hidden)和<textarea>生效,不响应disabled、contenteditable="false"或JS设置的readOnly属性;Safari≤15.3对number类型有漏匹配bug,select和button不支持,el.setAttribute('readonly', '')是可靠写法。

:read-only 伪类能用,但只对真实写了 readonly 属性的 <input>(非 type="hidden")和 <textarea> 生效;它不响应 disabled、contenteditable="false" 或 JS 动态设置的 element.readOnly = true —— 后者虽多数浏览器识别,但 SSR 或初始渲染可能漏样式。
哪些元素真正匹配 :read-only?
浏览器只看 DOM 中是否存在 readonly 这个布尔属性,不关心 JS 是否锁了输入逻辑:
-
<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⚠️ 多数浏览器认,但服务端渲染或首屏可能不一致
:read-only 和 :read-write 的语义差异
:read-write 表示“当前可编辑状态”,不是 :read-only 的简单取反:
-
<input readonly disabled>→ 不匹配任一伪类,只走:disabled -
<input disabled>→ 只匹配:disabled,:read-only和:read-write都不生效 -
<div contenteditable="true">→ 匹配:read-write,但 Safari 15.4 前有兼容问题 -
<div contenteditable="false">→ 规范说该匹配:read-only,但实际多数浏览器不认,得用[contenteditable="false"]
样式冲突与常见踩坑点
:disabled 的权重天然高于 :read-only,哪怕你把它写在后面,只要元素带 disabled 属性,:disabled 样式一定生效:
立即学习“前端免费学习笔记(深入)”;
- 别让
readonly和disabled同时存在——语义冲突:readonly字段仍可聚焦、可复制、会提交;disabled则彻底禁用 -
:read-only默认允许文本选择,想禁止需显式加user-select: none;想允许复制则加user-select: text - 只读输入框仍会接收 Tab 焦点,若查看模式下不想停在这里,得手动设
tabindex="-1" - IE 全系不支持这两个伪类,fallback 方案必须用
input[readonly]和textarea[readonly]
真正难处理的是混合状态下的焦点流和 SSR 渲染一致性——readonly 属性必须真实存在于 HTML 字符串中,JS 动态增删时务必同步 DOM 属性,不能只改 JS 属性。


















