:read-only仅匹配<input>(非hidden/checkbox等)和<textarea>;<select>、<button>、<div>、<input type="hidden">、<input type="checkbox">及contenteditable="false"元素均不匹配,即使显式添加readonly属性也无效。

:read-only 只对 <input>(非 hidden、checkbox 等类型)和 <textarea> 生效,其他元素写了也白搭。
哪些元素根本不会匹配 :read-only?
浏览器硬性限制,不是写法问题:
-
<select readonly>、<button readonly>、<div readonly>—— 全都不触发:read-only,哪怕 DOM 里真有这个属性 -
<input type="hidden">和<input type="checkbox">等不支持readonly属性的控件,加了也无效 -
contenteditable="false"的<div>或<span>不走:read-only,得用[contenteditable="false"]单独写
为什么明明加了 readonly 属性,样式还是没变?
伪类生效的前提是:浏览器真“认出”这个元素只读。常见断点在这里:
- JS 设置
el.readOnly = true不够 —— 必须调用el.setAttribute('readonly', ''),让属性真实写入 DOM - Vue/React 中用了
:readonly或readOnly,但没检查最终渲染出的 HTML 是否真带readonly字样(DevTools → Elements 面板里搜) -
readonly="false"或readonly="0"这种写法反而会生效(因为布尔属性“存在即为真”),但容易误导人;正确写法是readonly或readonly="" - Safari ≤15.3 对
type="number"的:read-only支持不全,老版本直接忽略
为什么 :read-only 和 :disabled 同时存在时样式不对?
这不是 bug,是浏览器语义优先级设计:
立即学习“前端免费学习笔记(深入)”;
- 如果一个
<input>同时有readonly和disabled属性,:disabled规则一定覆盖:read-only—— 因为disabled是更强的禁用状态 - 但二者行为完全不同:
:read-only元素仍可聚焦、可复制、会提交值;:disabled则完全跳过表单验证、不提交、不可聚焦 - 别为了“视觉灰掉”而滥用
disabled,该用readonly就用,样式上用background-color+color+cursor: not-allowed明确传达“只读”而非“禁用”
最常被忽略的一点::read-only 不影响表单验证逻辑,也不阻止 oninput 或 onchange 被 JS 手动触发 —— 它只是个样式钩子,不是功能锁。真要防改,还得靠后端校验和前端逻辑控制。


















