必须是的第一个子元素且仅含纯文本,任何嵌套、移位或隐藏都会破坏屏幕阅读器识别与wcag合规性。

<legend></legend> 必须作为 <fieldset></fieldset> 的第一个子元素,且只能是纯文本——这是唯一合法写法。任何嵌套、移位或样式干扰都会破坏可访问性,不是“看起来像就行”的事。
为什么<legend></legend>不能用<h3></h3>包裹或放错位置
屏幕阅读器(如 NVDA、VoiceOver)依赖 DOM 顺序识别分组语义。一旦 <legend></legend> 不在 <fieldset></fieldset> 开头,或被 <h3></h3>、<div> 包裹,就会出现跳读、重复读、甚至完全忽略该分组。
<ul>
<li>
<code><legend><h3>地址信息</h3></legend> → <h3></h3> 干扰可访问名称计算,读屏器可能只读“地址信息”或静音
<fieldset><div><legend>地址信息</legend></div></fieldset> → <legend></legend> 不再是第一个子元素,WCAG 检查直接报 fieldset-missing-legend
order 或 position: absolute 移动 <legend></legend> → 它脱离语义流,键盘焦点顺序错乱怎么安全地改<legend></legend>的样式
默认渲染中,<legend></legend> 嵌入边框左上角是 UA 样式实现的视觉效果,不是语义本身。你可以调样式,但必须守住两条底线:不破坏 DOM 顺序、不隐藏其可访问性。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 右对齐?用
text-align: right或margin-left: auto,别碰flex排序 - 视觉隐藏但保留语义?用标准
sr-only类(position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;),别写display: none或visibility: hidden - 禁用整组时,
<legend></legend>不响应disabled属性——这是对的;灰掉文字颜色需靠fieldset[disabled] legend单独加opacity或color
服务端或框架中容易漏掉的结构断裂点
动态渲染时,<legend></legend> 极易因逻辑分支覆盖不全而缺失,尤其在 SSR 或条件渲染场景下,这类错误 HTML 验证难发现,但 axe-core 会立刻报 aria-required-parent 错误。
- Vue/React 中用
v-if/ 条件渲染包裹整个<fieldset></fieldset>,但忘了确保<legend></legend>总在内部最前 - 后端模板(如 Jinja2、Twig)中,
{% if show_billing %}只包了<input>,没把<legend></legend>一起包进去 → 渲染出孤立的<legend></legend>,HTML 验证失败 - 模板里字段组开闭标签不匹配(比如漏写
),会导致后续所有<legend></legend>被解析为孤儿节点
真正难的不是写对一次,而是保证每次动态生成都守住 DOM 顺序和纯文本约束——它卡在语义链最前端,错一点,整组控件的可访问性就断了。










