legend必须是fieldset的首个直接子元素,否则屏幕阅读器无法建立分组语义;它不可被条件渲染、不可隐藏、不可嵌套块级元素,且fieldset内须含可聚焦控件。

legend 不是装饰性标题,它必须作为 fieldset 的第一个子元素存在,否则屏幕阅读器无法建立分组语义——这不是样式问题,是 DOM 结构失效。
legend 必须是 fieldset 的首个直接子元素
浏览器和辅助技术(如 NVDA、VoiceOver)只认一种结构:fieldset 开头紧跟着 legend,中间不能插任何东西。
-
<fieldset> <input><legend>地址</legend> </fieldset>→legend不是首子节点,部分 Safari 版本跳过播报 -
<fieldset><div><legend>支付方式</legend></div></fieldset>→legend被包裹,读屏器忽略分组语义 - React/Vue 中写
{show && <legend>...</legend>}会导致它被条件渲染“挤”到非首位,等价于缺失 - 正确写法只有一种:
<fieldset> <legend>收货地址</legend> <input name="addr"> </fieldset>,无空格、无注释、无嵌套标签
别用 display: none 隐藏 legend 文本
视觉上不想显示标题?display: none 或 visibility: hidden 会彻底移除其在可访问性树中的存在,等于没写 legend。
- 安全做法是用标准视觉隐藏类,保留在 DOM 中且可被读屏器识别
- 例如:
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } - 然后:
<legend class="visually-hidden">发票信息</legend> - 注意:这不是常规推荐操作,仅适用于已有视觉标题、需避免冗余播报的极少数场景
fieldset 内必须含可聚焦控件才能激活分组语义
只包 <p></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3458" title="html-ppt-to-pdf"><img
src="https://img.php.cn/upload/skill/000/000/081/178956546773641.jpg" alt="html-ppt-to-pdf" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill3458" title="html-ppt-to-pdf" class="overflowclass">html-ppt-to-pdf</a>
<p class="overflowclass">将使用 `<section class="slide">` 约定的 HTML 幻灯片转换为高保真、矢量文本 PDF(使用 Playwright + Chromium 原生 PDF 功能)。</p>
</div>
<a rel="nofollow" href="/xiazai/skill3458" title="html-ppt-to-pdf" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div> 或说明文字的 fieldset,浏览器可能不渲染边框,辅助技术也感知不到这是个“组”。
- 有效子元素包括:
input、select、textarea、button、input[type="radio"]等可交互控件 - 错误示例:
<fieldset> <legend>提示</legend> <p>请核对信息</p> </fieldset>→ 对读屏器基本无效 - 纯说明内容建议直接用
<div> + CSS,别硬套 <code>fieldset -
fieldset[disabled]只对直属可聚焦控件生效,不穿透嵌套层级(如<div><input></div>中的input不受影响) - 真正可控的方式只有两种:
text-align: center或text-align: right控制文字对齐(仅影响文字本身,不影响边框锚点);display: contents拆解默认盒模型(但 IE 完全不支持) -
<legend></legend>内部禁止嵌套块级元素(如<p></p>、<div>)或表单控件(如 <code><input>),否则触发 HTML 解析错误或布局异常 - 给
fieldset加aria-label或title属性,对大多数屏幕阅读器无效——它们只读legend文本 - 空
<legend></legend>或仅含空格,等同于无标题,不被识别
修改 legend 样式时容易踩的坑
浏览器对 legend 有特殊渲染逻辑:它“属于”边框的一部分,不是普通块级子元素。用 position: absolute 或 margin-left 等方式强行移动,往往导致边框断裂、文字重叠或布局错乱。
最难的不是手写一次正确结构,而是每次动态生成都守住 legend 必须是 fieldset 第一个子元素且仅含纯文本这条线——它卡在语义链最前端,错一点,整组控件的可访问性就断了。










