:read-only仅匹配带readonly属性的input(非range/checkbox等)和textarea,disabled元素不匹配该伪类;混用时:disabled样式优先覆盖,且readonly不阻止粘贴或js修改,仅作视觉提示。

:read-only 不能控制“禁用”输入框样式——它只响应 readonly 属性,而禁用状态应由 :disabled 处理。混用或误以为 :read-only 能替代 :disabled 是最常踩的坑。
为什么 :read-only 样式对 disabled 输入框完全不生效
浏览器严格区分语义::read-only 只匹配带 readonly 属性且原生支持该属性的 <input>(非 type="range"、"checkbox" 等)和 <textarea></textarea>;disabled 元素既不匹配 :read-only,也不匹配 :read-write,只能用 :disabled 选择。
-
<input disabled>→ 只触发:disabled,:read-only规则被忽略 -
<input readonly disabled>→ 同时存在两个属性,但:disabled样式一定覆盖:read-only(同权重下后声明者胜出,且浏览器内部优先级更高) - 试图写
input:read-only, input:disabled { background: #eee; }来统一视觉?可以,但 JS 逻辑里必须明确区分:前者值会提交,后者不会
真正想“禁用输入框”,该用 :disabled 还是 :read-only?
取决于交互需求:
- 要彻底禁用交互(不可聚焦、不可复制、不参与表单提交)→ 用
disabled属性 +:disabled样式 - 要保留可聚焦、可选中、可复制、值照常提交,仅禁止编辑 → 用
readonly属性 +:read-only样式 - 别用
readonly去模拟disabled:用户仍能Tab进去、右键粘贴、甚至通过控制台改value
:read-only 样式写出来却没反应?先盯死 DOM
样式失效几乎全是 DOM 层问题,不是 CSS 写错:
- 打开 DevTools → Elements 面板,确认目标元素标签上**真实存在
readonly字样**(如<input readonly>),而不是只在 JS 里写了el.readOnly = true - Vue 中用
v-bind:readonly="isReadonly",React 中用readOnly={isReadonly}(注意驼峰),否则属性根本不会渲染到 HTML - 原生 JS 切换状态时:
el.setAttribute('readonly', '')开启,el.removeAttribute('readonly')关闭;别用el.readOnly = false,Safari 15 及更早版本不识别 -
<select></select>、<button></button>、<input type="hidden">加了readonly也无效,:read-only不匹配它们
兼容性差又必须支持旧浏览器?别硬扛 :read-only
IE 全系不支持,Safari ≤15.3 对 type="number" 有漏匹配 bug,Firefox 需额外写 :-moz-read-only。稳妥降级方案只有一个:
- 统一用属性选择器:
input[readonly]和textarea[readonly],所有浏览器都支持,行为确定 - 如果项目已用
:read-only,加一层兜底:input[readonly], input:read-only, input:-moz-read-only - 千万别把
:read-only当安全机制——它只是视觉提示,后端必须校验字段是否被篡改
真正难处理的是「readonly 属性没出现在初始 HTML 字符串里」的场景,比如 SSR 渲染时状态没同步,或者 Shadow DOM 内部未用 ::slotted(input:read-only) 显式穿透。这些地方样式失效,往往查半天 CSS,其实问题在 DOM 构建阶段。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











