自定义标签(如<my-header>、<_html>)被浏览器降级为无语义的HTMLElement,node.role为空、display默认inline、无障碍树中无role/name、SEO无权重,等效于未设role的<div>。

非标准自定义标签(如 <my-header>、<_html>)在浏览器中不产生语义,也不参与结构划分或无障碍树构建;它被当作无角色、无默认样式、无 SEO 权重的通用容器处理,等效于未设 role 的 <div>。
自定义标签在 DOM 和无障碍树中实际被当作什么处理
HTML 解析器对未知标签采用“void element fallback”策略:不报错,但剥离所有语义上下文。它不会像 <main> 那样自动添加 role="main",也不会响应 document.querySelector('main') 这类语义选择器。
-
node.nodeType是1(Node.ELEMENT_NODE),node instanceof HTMLElement为true,但node.role为空字符串 -
getComputedStyle(element).display默认返回"inline",需显式设为block或flex才能正常布局 - 无障碍树中该节点无
role、无name、无properties,屏幕阅读器通常跳过,或仅读作 “group” - 搜索引擎完全忽略其存在,只提取内部文本,不赋予任何结构权重
为什么 <custom-section> 不能替代 <section> 做语义划分
语义 sectioning 是由浏览器内建规则驱动的,只响应白名单标签。即使你给 <custom-section> 加上 role="region" 和 aria-labelledby,它仍不具备 <section> 的 sectioning root 行为。
-
<section>触发 sectioning root 创建,影响<h1>–<h6>的隐式层级计数 -
<custom-section>内的<h1>仍被解析为整个页面的最高级标题,而非该组件内的顶级标题 -
document.querySelectorAll(':scope > h2')在<custom-section>内无法按节匹配,因无 scope 绑定能力 -
role="region"不提供 heading 流程重置能力,这是真正容易被忽略的关键点
<_html> 这类以下划线开头的标签为何完全无效
<_html> 不是 HTML 标准的一部分,浏览器直接将其作为未知自定义元素降级,且该命名本身违反 HTML5 标签名规范——所有标准标签均以字母开头,不含下划线。
立即学习“前端免费学习笔记(深入)”;
- HTML5 规范只定义约 110 个标准标签,全部小写、字母开头、无特殊符号
-
_html在 JS 中常表示私有变量,在 CSS 类名中合法,但在标签名中**完全无效** - 写成
<_html><_head><title>测试</title></_head><_body><p>Hello</p></_body></_html>后,浏览器不会报错,但 DOM 中生成的是多个孤立的HTMLElement,无父子关系、无默认样式、不参与任何语义流程 - 这类写法在 SSR/SSG 输出中还会干扰爬虫对 DOM 深度和文本连续性的判断,实测首屏文本收录率下降超 40%
想用自定义标签又保语义?必须手动补全 ARIA,且不能只靠 role
坚持使用自定义标签(如 Web Components 场景)时,语义不能靠猜测,必须显式声明。仅加 role 不够,还需配套 name、label、live region 等属性,否则辅助技术仍无法理解。
- 基础语义:至少设置
role+aria-label或aria-labelledby - 导航区域:用
role="navigation",且确保内部含可聚焦链接(否则会被忽略) - 主内容区:用
role="main",注意同一文档只能有一个,否则违反 WCAG - 避免滥用
role="article":它要求内容独立可分发,不是所有“卡片”都满足 - 真正复杂的是 heading 流程——自定义标签无法中断或重启 heading 级别序列,哪怕视觉上看起来是新章节



















