公開日: 2026 年 3 月 9 日
カスタム要素を使用すると、ウェブアプリ デベロッパーは独自の動作を持つ UI コンポーネントを構築、共有、再利用できるため、開発が容易になります。しかし、アプリでさまざまなカスタム要素のセットを組み合わせると、混乱が生じ、名前の衝突が発生する可能性があります。スコープ付きカスタム要素レジストリはこの問題を解決します。
Microsoft Edge チームがこの機能に取り組んできました。このたび、Edge と Chrome 146、およびその他の Chromium ベースのブラウザで、スコープ付きカスタム要素レジストリがデフォルトで利用可能になったことをお知らせします。カスタム要素をカプセル化できるようになり、コンポーネント ライブラリとマイクロ フロントエンド ライブラリのデベロッパーにとって長年の課題だった問題が解決されました。
スコープ付きカスタム要素レジストリは、ウェブ デベロッパーにとって重要なパターンを可能にします。複数のチームが個別に開発した複数のカスタム要素ライブラリや、同じライブラリの複数のバージョンを並行して使用できるようになりました。

スコープ付きカスタム要素レジストリとは
現在、ウェブページのすべてのカスタム要素の定義は、window.customElements の単一の共有レジストリに存在します。つまり、2 つの異なるライブラリが両方とも同じタグ名(<my-button> など)でカスタム要素を定義しようとすると、エラーがスローされ、ページが破損します。これは現実世界では大きな問題です。複数のチーム、デザイン システム、マイクロ フロントエンドからユーザー インターフェースを構成する大規模なアプリケーションでは、名前の衝突が簡単に発生する可能性があります。スコープ付きカスタム要素レジストリは、独立したレジストリを作成できるようにすることで、この問題を解決します。各レジストリは、グローバル レジストリや他のレジストリから完全に分離された独自のカスタム要素定義のセットを保持します。
新しいレジストリを作成する
すべてのカスタム要素をグローバル window.customElements レジストリで定義する代わりに:
new CustomElementRegistry()を呼び出して、新しいレジストリを作成します。- 新しいレジストリに特定のスコープを指定します(レジストリのスコープ設定をご覧ください)。
- 新しいレジストリに含める要素を定義します。
カスタム要素が使用されると、ブラウザは関連付けられたレジストリ(必ずしもグローバル レジストリとは限りません)から要素の定義を検索します。つまり、ページの異なる部分で、まったく異なるカスタム要素の定義を使用できるということです。
レジストリのスコープを設定する
カスタム要素レジストリは、ドキュメント、シャドー ルート、個々の要素のいずれかにスコープ設定できます。
シャドウ ルートにスコープを設定する
新しいレジストリをシャドー ルートにスコープするには、attachShadow() メソッドを呼び出すときに customElementRegistry オプションを使用します。シャドウルート内のすべてのカスタム要素は、対応するスコープ付きレジストリ内の定義を使用するようになります。
// Create your custom registry.
const registry = new CustomElementRegistry();
// Define a custom element in the new registry.
registry.define('my-card', class extends HTMLElement {
connectedCallback() {
this.textContent = 'Hello from scoped registry!';
}
});
// Create shadow root, providing it with your new custom element registry.
const host = document.querySelector('#host');
const shadow = host.attachShadow({
mode: 'open',
customElementRegistry: registry,
});
shadow.innerHTML = '<my-card></my-card>';
宣言型 Shadow DOM
<template> 要素の shadowrootcustomelementregistry 属性を使用して、結果のシャドウ ルートがグローバル レジストリではなくスコープ付きレジストリを使用していることをブラウザに伝えます。
<my-host>
<template shadowrootmode="open" shadowrootcustomelementregistry>
<my-widget></my-widget>
</template>
</my-host>
const registry = new CustomElementRegistry();
registry.define('my-widget', class extends HTMLElement {
connectedCallback() { this.textContent = 'Scoped!'; }
});
const shadow = document.querySelector('my-host').shadowRoot;
registry.initialize(shadow);
例に示すように、属性はカスタム要素レジストリのスペースを予約します。ユーザーは、切断されたドキュメントへのシャドウルート スコーピングにレジストリを定義して初期化する必要があります。
document.implementation.createHTMLDocument() で作成されたドキュメントなど、レジストリをドキュメントにスコープすることもできます。これにより、<template> 要素を複製し、オフスクリーン ドキュメント操作を行うことができます。それぞれに、コンポーネント定義の分離されたセットがあります。これを行うには、CustomElementRegistry.initialize() メソッドを使用します。
// Create a new registry.
const registry = new CustomElementRegistry();
registry.define('app-widget', AppWidget);
// Create a document, and use registry.initialize() to scope the registry to the document.
const doc = document.implementation.createHTMLDocument('');
registry.initialize(doc);
doc.body.innerHTML = '<app-widget></app-widget>';
個々の要素にスコープを設定する
customElementRegistry オプションを document.createElement() に渡すことで、レジストリを要素とそのサブツリーに直接関連付けることもできます。要素とその子孫は、DOM のどの部分に挿入されても、そのレジストリに対して解決されます。
// Create a registry and define a custom element in it.
const registry = new CustomElementRegistry();
registry.define('fancy-label', FancyLabel);
// Create a new DOM element and scope the new registry to it.
const el = document.createElement('fancy-input', {
customElementRegistry: registry,
});
// Use a custom element in the new DOM element.
el.innerHTML = '<fancy-label>Name</fancy-label>';
その他の情報
詳しくは、Edge のデモとそのソースコードをご覧ください。また、MDN の CustomElementRegistry リファレンス記事もご覧ください。
Chromium プロジェクトでのコラボレーションにより、Microsoft Edge と Chrome の両方で、また他の Chromium ベースのブラウザでも、スコープ付きカスタム要素レジストリがデフォルトで有効になりました。
設定を有効にしたり、オリジン トライアルに登録したりする必要はありません。Chromium ベースのブラウザでは、この機能を今すぐご利用いただけます。
他のブラウザでこの機能を実装する必要がある場合は、スコープ付きカスタム要素レジストリの問題に高評価を付け、ユースケースと回避策をコメントしてください。
Chromium ベースのブラウザで機能の実装に関するバグが見つかった場合は、crbug.com/new で問題を報告してください。
スコープ付きカスタム要素レジストリにより、ウェブ コンポーネントが使いやすくなることを願っています。