:read-only伪类仅匹配dom中真实存在readonly属性的文本类input(非hidden/checkbox等)和textarea,不响应js赋值el.readonly=true、disabled或contenteditable;safari≤15.3对number类型有漏匹配bug,select/button等不支持,ie全系不支持,推荐用[readonly]兜底。

:read-only 伪类只对真实存在 readonly 属性的 <input>(非 type="hidden")和 <textarea></textarea> 生效,不是“只要不能编辑就匹配”,也不是 JS 设置 el.readOnly = true 就能触发——它只看 DOM 属性是否在 HTML 字符串或通过 setAttribute 写入。
为什么 :read-only 样式没反应?先查 DOM 里有没有 readonly
常见现象:写了 input:read-only { background: #f5f5f5; },但输入框颜色没变。
- DevTools Elements 面板里看不到
readonly字样 → 说明属性根本没写进 DOM,:read-only不会触发 - 用了
el.readOnly = true但没调el.setAttribute('readonly', '')→ 多数浏览器不认,Safari 15 及更早版本一定失效 - Vue 中写
:readonly="isReadonly"是对的;React 中必须用readOnly={isReadonly}(驼峰),拼错成readonly就不会渲染属性 -
<input type="number" readonly>在 Safari ≤15.3 有漏匹配 bug,临时方案是改用type="text" inputmode="numeric"+ JS 拦截
哪些元素真正支持 :read-only?别往 select/button 上浪费时间
:read-only 的支持范围非常窄,浏览器只按规范实现,不扩展:
- ✅ 支持:
<input type="text">、<input type="email">、<input type="number">、<textarea></textarea> - ❌ 不支持:
<select></select>、<button></button>、<input type="checkbox">、<input type="hidden">、<div contenteditable="false"> <li>⚠️ 注意:<code><input readonly disabled>同时满足两个伪类,但:disabled样式会覆盖:read-only,哪怕你把它写在 CSS 后面 -
input[readonly]:只要属性存在就匹配,IE6+ 全支持,行为确定,推荐作为兜底或主方案 -
input:read-only:权重略高(0,1,0 > 0,0,1),但 Firefox 需补input:-moz-read-only,IE 完全不支持 - 别混用:
input[readonly] { … }和input:read-only { … }同时写,既冗余又易引发维护困惑 - 如果项目要兼容 IE 或旧版移动端 WebView,直接用
[readonly]更省心 - 仍可聚焦 → 若不想停在只读框上,得加
tabindex="-1" - 仍可双击/拖动选中文本 → 想禁止需显式加
user-select: none - 仍可右键粘贴 → 要拦截得监听
paste事件并event.preventDefault() - 值仍随表单提交 → 这是
readonly的语义,和disabled本质不同
:read-only 和 [readonly] 属性选择器,该选哪个?
两者效果常一样,但机制和兼容性差异明显:
:read-only 只负责样式,禁用交互得靠别的手段
它本身不阻止任何用户操作:
真正难处理的是 SSR 渲染一致性:服务端生成的 HTML 必须包含 readonly 属性,否则首屏就漏样式;JS 动态切换时,删属性必须用 removeAttribute('readonly'),而不是只设 el.readOnly = false。











