支持readonly的元素是<input>(text、email、number、date等文本类)和<textarea>;不支持的包括<select>、<checkbox>、<radio>、<button>、<output>、<label>、<div>及contenteditable元素。

readonly 属性只对 <input>(type 为 text、email、number、date 等文本类)和 <textarea> 有效,且必须配合 name 才能提交值;其他元素如 <select>、<checkbox>、<div> 或 contenteditable 元素不认它——硬加等于白加。
哪些元素支持 readonly?哪些不支持?
支持的:
- <input type="text">、<input type="email">、<input type="number">、<input type="date">(注意 iOS Safari 对 date 类型可能忽略)
- <textarea>(保留换行、滚动,完全可用)
不支持的:
-
<select>:Chrome/Firefox 忽略,Safari 行为不一致,别依赖 -
<input type="checkbox">或<input type="radio">:属性存在也无效,勾选状态照常切换 -
<button>、<output>、<label>、普通<div>:浏览器直接无视该属性 -
contenteditable元素:必须设contenteditable="false",readonly完全不起作用
readonly 和 disabled 到底怎么选?
选错会导致后端收不到字段,或用户交互断裂:
- 要“展示 + 可复制 + 可聚焦 + 值必须提交” → 用 readonly(例如订单号、预填邮箱、系统生成时间戳)
- 要“彻底禁用 + 不参与提交 + 视觉弱化 + 屏幕阅读器跳过” → 用 disabled(例如权限不足时灰掉的配置项)
- disabled 优先级高于 readonly:如果一个 input 同时有两者,disabled 生效,readonly 被覆盖
- fieldset[disabled] 不是只读方案:它会让所有子控件不可交互且默认不提交值,不能替代 readonly
JS 动态控制 readonly 的正确写法
DOM 属性名是 readOnly(驼峰),不是 readonly(小写):
- ✅ 正确:el.readOnly = true 或 el.readOnly = false
- ❌ 错误:el.readonly = true(小写,无效)
- ❌ 错误:el.setAttribute('readonly', 'false')(布尔属性不看值,只要存在就只读)
- ✅ 可以:el.setAttribute('readonly', '') 或 el.removeAttribute('readonly'),但不如直接赋值可靠
- React/Vue 中注意大小写:readOnly={condition}(React),不是 readonly={condition}
- 检查状态用 if (el.readOnly),不是 el.hasAttribute('readonly')(后者无法反映 JS 动态设置结果)
样式和无障碍必须补上
默认 readonly 输入框和可编辑的一模一样,用户根本看不出区别:
- 用 input:read-only 或 textarea:read-only 伪类加视觉提示:
background-color: #f9f9f9; cursor: default; border-color: #ddd;
- 避免仅靠颜色区分(色弱用户难识别),必须配 cursor: default
- 为无障碍考虑,显式加 aria-readonly="true"(尤其对非标准封装组件)
- 如果用了 contenteditable,光加 readonly 没用,得结合 contenteditable="false" + tabindex="-1" + user-select: none + pointer-events: none 才算完整
最容易被忽略的是:表单提交靠的是 name,不是 id 或是否可见;readonly 字段若没写 name,或者被 display: none 包裹,后端照样收不到。还有,type="number" 的 readonly 输入框提交的是字符串,后端模型绑定要能处理。



















