:read-only常不生效是因为仅匹配显式含readonly属性的(非hidden等类型)和;el.readonly=true无效,须用setattribute('readonly', '');select、div等不支持,且disabled会覆盖其样式。

为什么:read-only经常不生效?先确认元素真“只读”
浏览器只对**显式带有 readonly HTML 属性**的 <input>(非 type="hidden"、type="checkbox" 等)和 <textarea></textarea> 匹配 :read-only。
- el.readOnly = true 不触发样式,必须用 el.setAttribute('readonly', '')
- <select readonly></select>、<div readonly>、<code>contenteditable="false" 全都不匹配
- DevTools 里检查 Elements 面板,确认 readonly 字样真实出现在标签上,不是只在 JS 里赋了值
input:read-only 和 input[readonly] 到底该用哪个?
优先写 input[readonly], textarea[readonly],再补 input:read-only, textarea:read-only:
- [readonly] 是属性选择器,兼容性好(IE9+),行为确定,“有属性就匹配”,不依赖运行时状态
- :read-only 是伪类,语义更准(反映真实可编辑性),但 Safari 15.4 前对 type="number" 有 bug,旧版 Edge/IE 完全不支持
- 不要写 input[readonly="true"]——readonly 是布尔属性,readonly="" 或 readonly="anything" 都算存在
只改背景色不够,这些样式必须同步设置
单设 background-color: #f5f5f5 容易导致视觉割裂或误判为禁用:
- 必须加 color: #666,避免文字在浅灰背景上对比度不足
- 加 border-color: #ddd,否则边框可能还是默认蓝/黑,显得突兀
- 加 cursor: not-allowed,比仅改背景更能传达“不可编辑”意图
- 加 user-select: none,防止用户意外选中内容(只读 ≠ 可复制)
- 若需阻止聚焦,手动加 tabindex="-1";移除只读时别忘了同步移除它
和 :disabled 混用会出什么问题?<input readonly disabled> 同时满足两个伪类,但:
- :disabled 样式一定覆盖 :read-only,哪怕你把它写在后面
- :disabled 默认带 opacity、灰文字、无交互,会吃掉你为只读设计的浅灰背景和锁图标
- 语义冲突:readonly 表示“值要提交、可复制、可聚焦”,disabled 表示“不参与表单、不提交、不可聚焦”
- 实际项目中,二者不应共存;需要禁用交互时,优先用 readonly + tabindex="-1" + user-select: none,而不是加 disabled
input:read-only 和 input[readonly] 到底该用哪个?
优先写 input[readonly], textarea[readonly],再补 input:read-only, textarea:read-only:
- [readonly] 是属性选择器,兼容性好(IE9+),行为确定,“有属性就匹配”,不依赖运行时状态
- :read-only 是伪类,语义更准(反映真实可编辑性),但 Safari 15.4 前对 type="number" 有 bug,旧版 Edge/IE 完全不支持
- 不要写 input[readonly="true"]——readonly 是布尔属性,readonly="" 或 readonly="anything" 都算存在
只改背景色不够,这些样式必须同步设置
单设 background-color: #f5f5f5 容易导致视觉割裂或误判为禁用:
- 必须加 color: #666,避免文字在浅灰背景上对比度不足
- 加 border-color: #ddd,否则边框可能还是默认蓝/黑,显得突兀
- 加 cursor: not-allowed,比仅改背景更能传达“不可编辑”意图
- 加 user-select: none,防止用户意外选中内容(只读 ≠ 可复制)
- 若需阻止聚焦,手动加 tabindex="-1";移除只读时别忘了同步移除它
和 :disabled 混用会出什么问题?<input readonly disabled> 同时满足两个伪类,但:
- :disabled 样式一定覆盖 :read-only,哪怕你把它写在后面
- :disabled 默认带 opacity、灰文字、无交互,会吃掉你为只读设计的浅灰背景和锁图标
- 语义冲突:readonly 表示“值要提交、可复制、可聚焦”,disabled 表示“不参与表单、不提交、不可聚焦”
- 实际项目中,二者不应共存;需要禁用交互时,优先用 readonly + tabindex="-1" + user-select: none,而不是加 disabled
:disabled 混用会出什么问题?<input readonly disabled> 同时满足两个伪类,但:
- :disabled 样式一定覆盖 :read-only,哪怕你把它写在后面
- :disabled 默认带 opacity、灰文字、无交互,会吃掉你为只读设计的浅灰背景和锁图标
- 语义冲突:readonly 表示“值要提交、可复制、可聚焦”,disabled 表示“不参与表单、不提交、不可聚焦”
- 实际项目中,二者不应共存;需要禁用交互时,优先用 readonly + tabindex="-1" + user-select: none,而不是加 disabled
真正容易被忽略的是:伪类只管样式,不管行为。即使写了 input:read-only { cursor: not-allowed },用户仍能右键粘贴、按 Ctrl+A 全选、Tab 进入——这些都得靠额外属性或 JS 拦截。











