:read-only伪类仅对含readonly属性的input(非hidden)和textarea生效,不响应disabled或JS设置;Safari≤15.3对number类型有漏匹配bug,select和button完全不支持。

:read-only 伪类只对真实写了 readonly 属性的 <input>(非 type="hidden")和 <textarea></textarea> 生效,不响应 disabled、contenteditable="false" 或仅 JS 设置的 el.readOnly = true;Safari ≤15.3 对 type="number" 有漏匹配 bug,<select></select> 和 <button></button> 完全不支持。
怎么确认 :read-only 真生效了?
浏览器只检查 DOM 中是否存在 readonly 这个 HTML 属性,不关心 JS 是否锁了逻辑。打开 DevTools → Elements 面板,看目标元素标签上有没有 readonly 字样(哪怕写成 readonly="" 或 readonly="anything" 都行)。
-
el.setAttribute('readonly', '')是最稳妥的写法,确保属性真实落进 DOM -
el.readOnly = true多数浏览器能识别,但 SSR 或首屏渲染可能漏掉样式 -
<input readonly>直接写在 HTML 里最可靠——布尔属性只要出现就生效
哪些元素能被 :read-only 匹配?别试错方向
:read-only 只对原生支持 readonly 的文本类表单控件生效:
-
<input type="text">、<input type="email">、<input type="number">✅(注意:Safari ≤15.3 对type="number"有漏匹配 bug) -
<textarea></textarea>✅ -
<select readonly></select>❌ 不支持,HTML 规范不承认 <div contenteditable="false"> ❌ 不是表单控件,伪类无效 <li> <code><input type="checkbox">❌ 即使加了readonly,也不在匹配范围内- 背景别太暗:
background-color: #f9fafb(比:disabled的#f4f4f5略亮) - 文字保持原色:
color: #111827(不降权,强调数据真实) - 光标设为
cursor: default,不是not-allowed(后者暗示错误或禁用) - 允许复制:
user-select: text;如需禁止,则加user-select: none - 边框保留结构感:
border: 1px solid #d1d5db,而非border: none
特别注意:<input readonly disabled> 会走 :disabled,:read-only 完全不生效——两者语义冲突,不能混用。
立即学习“前端免费学习笔记(深入)”;
只读框的样式怎么写才不误导用户?
关键不是“灰掉”,而是让用户一眼分清“这是内容,不是被禁用”:
示例 CSS:
input:read-only, textarea:read-only {
background-color: #f9fafb;
border: 1px solid #d1d5db;
color: #111827;
cursor: default;
user-select: text;
}
容易被忽略的边界行为
真正卡住人的不是语法,是隐含假设:
-
:read-only不拦截任何事件:用户仍可右键粘贴、Ctrl+A全选、Tab键停在上面——要禁粘贴得自己监听paste并preventDefault() -
<input type="number">在 Safari 15.4 之前有 bug,:read-only可能不触发,得 fallback 到[readonly] - 只读框仍会接收焦点,查看模式下若不处理
tabindex="-1",键盘用户会意外停在这里
最常被跳过的一步:没检查最终 DOM 是否真带 readonly 属性——所有样式问题,八成出在这儿。


















