自定义元素在ie及旧edge中不被支持,需特性检测并降级;默认display为inline须重置;safari 16.4前form-associated元素不加入form.elements;无障碍需手动设置role与aria-*属性。

自定义元素在IE和旧版Edge里根本不会注册
浏览器不识别 <my-button></my-button> 这类标签,不是样式没生效,是 DOM 根本没创建——document.querySelector('my-button') 返回 null,customElements.define() 在 IE11 及更早版本直接报错 ReferenceError: customElements is not defined。
这不是“兼容性差”,而是规范缺失:Custom Elements v1(即 customElements.define())仅被 Chrome 67+、Firefox 63+、Safari 10.1+、Edge 79+ 原生支持。IE 全系列、旧 Edge(≤18)完全无此 API。
- 必须用特性检测替代 UA 判断:
if ('customElements' in window),而不是if (/MSIE|Trident/.test(navigator.userAgent)) - 若需支持 IE,只能降级为普通
<div class="my-button"> + 手动 JS 初始化,无法复用 <code>define()流程 - Webpack 构建时,不要把
customElements.define()放进默认 bundle;可用动态import()按需加载,或用try/catch包裹并 fallback - 基础重置建议放在 CSS 文件最开头:
my-card, my-input, my-dialog { display: block; } - 别只写常用几个,漏掉某个未使用的标签(如
<my-tooltip></my-tooltip>),后续上线后 JS 动态插入就会布局错乱 - 避免用通配符重置:
[is]:not([is=""]) { display: block; }不可靠,部分浏览器对属性选择器解析不稳定 - 检查方式:
const el = document.querySelector('my-input'); console.log(el.form?.elements.namedItem('my-input'))—— Safari 16.3 返回undefined - 兜底方案:手动收集所有自定义表单控件,统一调用
checkValidity()和setCustomValidity() - 别依赖
formdata事件自动收集值;Safari 旧版中该事件不触发,得靠submit时遍历 DOM 手动序列化 - 初始化时就要设:
this.setAttribute('role', 'switch'); this.setAttribute('aria-checked', 'false'); - 响应用户操作后,立刻同步:
this.setAttribute('aria-checked', this.checked.toString()); - 别只写
role="switch"就完事;缺少aria-labelledby或aria-label,屏幕阅读器仍无法理解控件用途
自定义标签的 display 默认是 inline,不是 block
即使你写了 <my-card></my-card> 并希望它像 <section></section> 那样独占一行,浏览器仍按 display: inline 渲染——margin、width、height 全部无效,除非显式重置。
这跟 HTML5 语义标签(如 <header></header>)不同:后者虽也需 display: block 兜底,但至少能被 html5shiv 注册;而自定义元素连注册都依赖现代 API,CSS 重置必须主动写。
form-associated 自定义元素在 Safari 16.4 之前不触发 form.elements
设了 formAssociated: true 并调用 attachInternals() 后,在 Safari ≤16.3 中,该元素不会出现在 form.elements 集合里,form.reportValidity() 也跳过它——验证逻辑形同虚设。
这不是 bug,是 Safari 对 Web Components 表单集成的实现延迟。Chrome 和 Firefox 从支持 Custom Elements v1 起就同步支持了 formAssociated,但 Safari 直到 16.4(2023 年中)才补全。
无障碍支持必须手动注入 role 和 aria-*,不能靠标签名
<my-toggle></my-toggle> 在 DOM 中只是裸的 HTMLElement,el.role 是空字符串,el.getAttribute('role') 也是 null。屏幕阅读器不会读作 “switch”,只会读成 “group” 或直接跳过。
自定义元素没有语义继承机制,role 和 aria- 属性必须显式设置,且要随内部状态同步更新——比如切换开/关时,aria-checked 必须实时改。











