:read-only 仅匹配具有 readonly 布尔属性(无论值为何)的 <input> 和 <textarea>,不作用于 <select>、<button> 或 contenteditable 元素;它反映真实只读状态,不拦截粘贴,且与 :disabled 行为不同。

怎么用 :read-only 选中真正只读的表单元素
它只匹配 readonly 属性存在且值为真(不关心具体值)的 <input>、<textarea>,不匹配 disabled 或仅靠 JS 阻止输入的元素。浏览器按 HTML 规范判定,不是看有没有响应用户输入。
-
readonly是布尔属性,写readonly或readonly="readonly"效果一样;但readonly="false"依然算只读——HTML 里布尔属性只要出现就生效 -
<select>和<button>不支持:read-only,哪怕加了readonly属性也没用,会被忽略 -
contenteditable="true"的<div>不受:read-only影响,这个伪类只作用于表单控件
:read-only 和 :disabled 容易混淆的边界
两者样式可共存,但语义和行为完全不同::disabled 元素不提交、不可聚焦、键盘事件完全被拦截;:read-only 元素仍可聚焦、可复制、会随表单提交,只是不能编辑。
- 如果给一个
<input readonly disabled>写样式,:read-only和:disabled都会命中,但:disabled优先级更高(同权重时后声明的胜出) - 用 JS 动态移除
readonly属性后,:read-only立即失效;但用element.readOnly = false操作 DOM 属性,同样会触发样式重绘 - 不要指望
:read-only拦截粘贴——用户仍可右键粘贴,需额外监听paste事件并preventDefault()
兼容性与实际能用的场景
Chrome 15+、Firefox 19+、Safari 3.1+、Edge 12+ 都支持,IE 完全不支持。如果你的项目还要兼容 IE,就得用 class 模拟,比如 .is-readonly。
- 适合做视觉反馈:灰掉背景、加锁图标、禁用光标
cursor: not-allowed,但别只靠它防用户改数据 - 常用于表单预览页,比如订单确认环节把收货地址设为
readonly,再用:read-only统一加底纹 - 注意 Safari 对
textarea[readonly]的:read-only样式有时延迟生效,建议加transform: translateZ(0)强制硬件加速触发重绘
为什么有时候写了 :read-only 却没效果
最常见原因是元素没真正带上 readonly 属性,或者用了错误的写法。
立即学习“前端免费学习笔记(深入)”;
- 写成
<input readonly="false">—— 这个依然只读,因为readonly是布尔属性,值是什么不重要 - 写成
<input readonly="off">—— 同样无效,只要属性存在就只读 - JS 里用
el.setAttribute('readonly', 'false'),结果还是只读;正确做法是el.removeAttribute('readonly') - CSS 选择器权重太低,被其他规则覆盖,比如
input[type="text"]比:read-only权重高,得写成input:read-only或input[readonly]:read-only
真正只读的状态必须来自 HTML 属性或 DOM readOnly 属性,CSS 伪类不会“创造”只读状态,它只是反映它。










