:read-only伪类仅匹配显式设置readonly属性的input/textarea,不控制行为;样式失效主因是dom无readonly属性、元素类型不支持或浏览器兼容问题。

直接用 input:read-only 和 textarea:read-only 就能生效,但前提是 HTML 里真有 readonly 属性——不是 disabled,不是 JS 赋值 el.readOnly = true,更不是 contenteditable="false"。
为什么 :read-only 样式没反应?先查这三件事
伪类不触发,90% 是因为元素压根没进入浏览器认定的“只读”状态:
-
readonly必须是 HTML 属性,写成<input readonly>或<input readonly>都行;readonly="false"也照样匹配(属性存在即生效) -
<select readonly></select>、<button readonly></button>、<div contenteditable="false"> 全都不匹配 —— <code>:read-only只认<input>(非hidden、checkbox等)和<textarea></textarea> - JS 动态设置时,用
el.setAttribute('readonly', ''),别只写el.readOnly = true;后者在 SSR 或初始渲染中可能不同步 -
input[readonly]兼容 IE9+,行为确定,只要属性在 DOM 里就命中 -
input:read-only是语义更准的伪类,但 Safari 15.4 前对type="number"有漏匹配 bug - 两者并列写,既覆盖现代逻辑,又兜底旧环境;避免单独依赖
:read-only导致部分浏览器样式丢失 - 显式加
padding: 4px 8px(或按你设计系统统一值),补回被 border 占用的空间 - 设
background-color: #f9fafb(比:disabled的#f4f4f5略亮),强调“这是数据,不是锁死” - 用
cursor: default替代not-allowed,避免和禁用状态混淆;加user-select: text允许复制 - 如果用了框架(如 Bootstrap),检查它是否定义了
.form-control:read-only,需针对性覆盖 - 若查看模式下不想让用户停在只读字段上,得手动加
tabindex="-1" - 别忘了
input:read-only:focus或input[readonly]:focus,否则某些浏览器会显示默认 outline -
:read-only不影响表单验证(值仍会提交),而:disabled会跳过验证且不提交 —— 语义不能混
input:read-only 和 input[readonly] 选哪个?
优先写 input:read-only, input[readonly] 并列选择器:
常见视觉优化组合:别只砍边框
只设 border: none 容易让输入框“塌掉”或文字贴边,必须同步调整其他属性:
容易被忽略的焦点与可访问性问题
只读输入框仍能获得焦点、响应 Tab 键,这点常被当成 bug 处理,其实是规范行为:
真正难处理的是后端返回的字段没带 readonly 属性,前端却要按逻辑只读。这时候伪类完全无能为力,只能靠 class 控制,:read-only 从来就不是“逻辑只读”的开关,它只认 HTML 属性是否存在。











