浏览器将私有标签静默降级为HTMLUnknownElement,不赋予语义角色、sectioning行为或默认样式,仅作普通容器处理;即使添加role属性,也需手动补全ARIA状态、焦点逻辑与name来源,且无法替代原生语义标签的结构功能。

浏览器怎么处理这类私有标签
它根本不会当语义元素看,而是直接降级为无角色、无样式的 HTMLElement,DOM 里节点类型是 HTMLUnknownElement,但 constructor.name 可能还是 HTMLElement(取决于浏览器),真正可靠判断方式是查 element.constructor.name === 'HTMLUnknownElement'。
这种降级不是报错,而是静默剥离:不触发 landmark 角色、不参与 sectioning、无障碍树里没 role、没 name、屏幕阅读器读作“group”或直接跳过。你写 <my-header role="banner"></my-header>,role 属性虽存在,但浏览器不会自动补 aria-label 或绑定焦点逻辑——全得手动填。
- display 默认是
inline,不是block,所以即使写了width/height也无效,必须显式设display: block或flex - 无法被
document.querySelector('header')匹配,只能靠querySelector('my-header')或属性选择器 - 搜索引擎不识别其结构意图,只当普通容器提取文本,无 SEO 权重
为什么加了role="region"还是不能替代
因为 sectioning root 行为是硬编码在浏览器解析器里的白名单机制,<section></section> 触发 heading 级别重置、影响 :scope > h2 选择、形成独立节上下文;而 <custom-section></custom-section> 即使加了 role="region" 和 aria-labelledby,heading 层级仍沿用父级计数——<h1></h1> 在里面还是页面级 h1,不是该组件内的顶级标题。
更关键的是,它不会创建新的 sectioning root,所以 document.querySelectorAll(':scope > h2') 在 <custom-section></custom-section> 内执行,实际匹配的是整个文档的 h2,不是该标签内部的子 h2。
立即学习“前端免费学习笔记(深入)”;
-
<section></section>自动成为sectioning root,影响 heading 隐式层级和节内选择逻辑 -
role="region"仅提供辅助技术可访问性,不改变 DOM 节构或 CSS 作用域 - 若需语义分节,必须用标准标签;私有标签只能靠 ARIA 手动模拟,且无法覆盖所有浏览器内置行为
想用 Web Components 又保语义?ARIA 补全要到什么程度
光写 role 远不够。比如自定义导航栏 <my-nav></my-nav>,只加 role="navigation",屏幕阅读器可能读成“navigation”,但内部链接若没 tabindex="0" 或不是原生可聚焦元素,就无法键盘操作;若没 aria-label 或 aria-labelledby,连“这是哪个导航”都说不清。
真正容易被忽略的是 name 来源和交互反馈。ARIA name 必须可计算(来自 aria-label、aria-labelledby、元素文本内容等),且不能为空;如果组件含动态内容,还得配合 aria-live 声明更新策略。
- 基础语义:至少
role+aria-label或aria-labelledby - 导航区域:
role="navigation"+ 内部含可聚焦链接(a、button或带tabindex="0"的元素) - 主内容区:
role="main",但全文档只能有一个,重复会违反 WCAG - 避免滥用
role="article":它要求内容独立可分发,不是所有卡片都满足
IE8 及以下对私有标签和 HTML5 标签的处理差异
IE8 及以下对两者其实没区别——都当未知标签处理,但后果不同:<header></header> 是 HTML5 标准标签,可通过 document.createElement('header') 注册后被识别为合法元素,再配合 CSS 设 display: block 就能渲染;而 <my-header></my-header> 是纯私有标签,即使注册了,IE 也不会给它任何默认样式或语义,且现代 polyfill(如 html5shiv)根本不处理非标准标签。
换句话说,html5shiv 解决的是“浏览器认不认识这个标签名”,不是“这个标签有没有语义”。它能让 IE 把 <section></section> 当成块级元素渲染,但对 <my-section></my-section> 完全无效。
- IE8 中
document.createElement('my-header')成功,但getComputedStyle(myHeader).display仍是"inline" - css 选择器
my-header { display: block; }在 IE8 中完全不生效,因解析器未将该标签纳入样式匹配流程 - 若坚持用私有标签兼容旧 IE,必须手写内联脚本批量注册 + 内联 style 强制设 display,且无法获得任何语义保障



















