只读表单字段应使用 :read-only 伪类而非 :disabled,配合 cursor: default、background-color: #f9fafb、user-select: text 实现视觉区分与可交互性;需动态切换 readonly 属性而非仅设置 readonly 属性,注意浏览器兼容性及元素类型限制,并额外拦截粘贴、全选等行为。

只读表单字段需要视觉区分但又得保持可交互
最典型场景是订单确认页、用户资料预览页——字段不能改,但要允许复制(如订单号、手机号)、聚焦查看、双击选中。这时候用 :read-only 加 cursor: default + background-color: #f9fafb + user-select: text,比 :disabled 更准确:后者会禁焦点、不提交值、灰化严重,语义和行为都错位。
需要响应 JS 动态切换只读状态的编辑模式
比如点击「编辑」按钮后输入框变可写,再点「保存」恢复只读。用 el.setAttribute('readonly', '') 和 el.removeAttribute('readonly') 触发 :read-only 样式自动切换,比手动增删 class 更轻量。注意别只写 el.readOnly = true,SSR 或首屏渲染可能漏掉属性,导致样式不生效。
-
:read-only在 Chrome 14+、Firefox 17+、Safari 3.1+、Edge 12+ 均可用,但 Firefox 要写input:-moz-read-only才兼容 - 别和
:disabled混用:同时存在时:disabled样式会覆盖:read-only,且语义冲突(一个提交值,一个不提交) -
<input type="number">在 Safari ≤15.3 有 bug,:read-only可能不触发,得 fallback 到input[readonly]
避免误用于不支持的元素类型
:read-only 只对原生支持 readonly 属性的文本类控件生效:<input type="text">、<input type="email">、<textarea></textarea>。以下情况写了也白搭:
-
<select readonly></select>—— HTML 规范不支持,浏览器直接忽略 -
<button readonly></button>或<input type="checkbox" readonly>—— 不在匹配范围内 <div contenteditable="false"> —— 属于富文本范畴,得用 <code>[contenteditable="false"]-
<input type="hidden">—— 无交互界面,伪类不作用 - 禁粘贴:监听
paste事件并调用event.preventDefault() - 跳过焦点:加
tabindex="-1"(尤其查看模式下不想让用户停在只读框) - 禁文本选择:显式设
user-select: none(默认是text)
真正容易被忽略的是它不控制行为
:read-only 是纯样式钩子,不是功能开关。用户仍可右键粘贴、Ctrl+A 全选、按 Tab 停留、双击选中——这些都得靠额外手段拦截:
最常翻车的地方,是以为加了 :read-only 就等于“锁死了”,结果测试时发现用户照常能粘贴、能全选、能意外修改(如果 JS 逻辑没同步校验)。它只解决“看起来是只读的”,不解决“真的不能动”。











