fieldset 必须以非空 legend 为首个子元素才能实现语义分组、可访问性支持和 disabled 属性继承;legend 不可为空、不可被 display:none 隐藏,disabled 仅作用于直接子控件,嵌套需谨慎,显隐应避免 display:none 而用 inert+aria-expanded。

fieldset 必须配 legend 才能生效
没有 legend 的 fieldset 在语义、可访问性和行为上基本等于没写。Chrome 和 Firefox 渲染时会忽略其边界,屏幕阅读器读作“未命名组”,disabled 属性也无法向下传递到子控件。
常见错误包括:<legend></legend>(空标签)、<fieldset>
<input><legend>地址</legend>
</fieldset>(legend 不是首子元素)、或用 div 包裹后再塞进 fieldset(中断继承链)。
-
legend必须是fieldset的第一个子节点,内容需非空且具业务含义,如<legend>收货信息</legend> - 视觉隐藏可用
position: absolute; clip: rect(1px, 1px, 1px, 1px),禁用display: none或visibility: hidden - 不要用
aria-label替代legend—— 它无法触发原生disabled继承
disabled 属性只作用于直系表单控件
fieldset[disabled] 看似一键禁用整组,但实际生效范围很窄:仅对 input、select、textarea、button、input[type="radio"] 等**直接子级**有效。一旦中间插了 div 或 section,禁用就断了。
典型失效场景:<fieldset disabled><div><input name="email"></div></fieldset> —— 这个 input 依然可聚焦、可编辑、值仍会提交。
- 禁用整组时,确保控件是
fieldset的直接子元素,而非嵌套在任意容器内 - 若布局需要包裹,用
span或 CSS Grid/Flex 布局替代div,避免语义中断 - 键盘 Tab 测试是唯一可靠验证方式:焦点不该停在任何被禁用的控件上
嵌套 fieldset 容易破坏焦点流
虽然 HTML 允许嵌套 fieldset,但 ≥3 层嵌套极易导致键盘导航卡顿或跳过某一层。尤其当内层 legend 缺失、被隐藏,或含交互元素(如 button)时,焦点可能“陷”在中间层出不来。
UI 框架(如 Ant Design)常剥离 fieldset,只保留视觉结构。上线前务必检查真实 DOM,确认每层都有语义清晰的 legend,且未被框架抹除。
- 优先用单层
fieldset+ CSS 视觉分隔(如margin-top、边框)替代深层嵌套 - 必须嵌套时,每层都加非空
legend,且内部不放button、a等可聚焦元素 - 用
console.log(document.activeElement)实时观察 Tab 路径,比依赖默认行为更准
收起/展开不能用 display: none
用 display: none 或 visibility: hidden 控制 fieldset 显隐,会彻底切断可访问性树和 disabled 继承,屏幕阅读器直接跳过该组,用户也无法通过键盘导航到达其中控件。
正确做法是结合 inert 属性与 aria-expanded,再用 max-height + overflow: hidden 实现过渡动画。
- 收起时:加
inert+aria-expanded="false";展开时移除inert+aria-expanded="true" - CSS 动画用
max-height,别用height(无法自动适配内容高度) - 若
fieldset已disabled,inert可省略 ——disabled本身已阻断所有交互
legend 的位置约束和 disabled 的继承边界。不是写了 fieldset 就算完成逻辑分组,而是每个标签的位置、顺序、父/子关系都直接影响浏览器解析与辅助技术行为。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











