系统设置页面必须用,哪怕不提交后端,因其提供原生语义、Tab/Enter交互及无障碍支持;纯会导致键盘导航失效、回车无响应、屏幕阅读器无法关联label与input,直接违反WCAG 2.1。

系统设置页面必须用 <form></form>,哪怕不提交到后端——这是语义、键盘交互和无障碍支持的底线,不是可选项。
为什么不能用 <div> 包裹设置项
<p>纯 <code><div> 布局会让 Tab 键跳过所有输入框,Enter 键在任意焦点控件上都不触发保存,屏幕阅读器无法把 <code><label></label> 和对应 <input> 关联起来。WCAG 2.1 直接不通过。
实操建议:
-
<form></form>可以没有action和method,空标签仍保有完整表单语义 - 每个
<input>必须配<label for="xxx"></label>或包裹式写法<label>文本<input></label> - 禁用
onsubmit="return false"这类粗暴拦截;JS 中统一用event.preventDefault()控制逻辑
<fieldset></fieldset> + <legend></legend> 是唯一合法的分组方式
用 <h3></h3> 或 <div class="group"> 模拟分组,会导致键盘导航断层、打印样式错乱、iOS VoiceOver 读不出分组关系。<p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p>
<p>常见错误现象:</p>
<ul>
<li>嵌套多层 <code><fieldset></fieldset> → 旧版 Safari 渲染丢失 <legend></legend>
disabled 属性 → 无法一键灰掉“高级模式”下整组控件<legend></legend> 写在 <fieldset></fieldset> 外面 → 语义断裂,浏览器不识别正确结构示例:
<fieldset> <legend>网络设置</legend> <label>代理地址</label> <input type="text" name="proxy_host"> <label>启用 HTTPS 代理</label> <input type="checkbox" name="use_https_proxy"> </fieldset>
input[type="number"] 输不了小数点或负号?是浏览器在守规范
Chrome 和 Safari 默认把 step="1" 和无 min 当作“只接受整数”的信号,拦截 - 和 . 是故意行为,不是 bug。
实操建议:
- 要输小数:显式写
step="0.1"或更宽松的step="any" - 要输负数:必须设
min="-100"(哪怕只是占位) - 别依赖 type 校验:用户仍可粘贴非法字符串,JS 需监听
input事件过滤 - 移动端补救:加
inputmode="decimal",比单纯type="number"更可靠
保存按钮必须是 <form></form> 内的 type="submit"
外置按钮 + form="id" 在 Safari 14 以下不兼容,且无法保证回车提交时的焦点同步和表单状态一致性。
关键细节:
- 按钮必须在
<form></form>标签内部,不能靠 CSS 定位“看起来在里面” - 点击后需立即禁用,防重复提交:
button.disabled = true,而不是仅视觉置灰 - 若用 JS 提交,仍应保留
type="submit"并在onsubmit中preventDefault,否则破坏原生聚焦流
最易被忽略的一点:当设置项里混入动态加载的子模块(比如插件配置区),它们也必须挂载在同一个 <form></form> 下,否则 FormData 无法一并采集,JS 手动拼数据极易漏字段或类型错乱。



















