Faire en sorte que les éléments personnalisés se comportent avec des registres de portée

Jayson Chen
Jayson Chen
Patrick Brosset
Patrick Brosset

Date de publication : 9 mars 2026

Les éléments personnalisés permettent aux développeurs d'applications Web de créer, partager et réutiliser des composants d'UI avec leurs propres comportements, ce qui facilite le développement. Toutefois, lorsque votre application regroupe différents ensembles d'éléments personnalisés, les choses peuvent devenir compliquées et des conflits de noms peuvent survenir. Les registres d'éléments personnalisés à portée limitée résolvent ce problème !

L'équipe Microsoft Edge a travaillé sur cette fonctionnalité. Nous sommes heureux d'annoncer que les registres d'éléments personnalisés à portée limitée sont désormais disponibles par défaut à partir d'Edge et de Chrome 146, ainsi que d'autres navigateurs basés sur Chromium. Vous pouvez désormais encapsuler des éléments personnalisés, ce qui résout un problème de longue date pour les développeurs de composants et de bibliothèques de micro-frontends.

Browser Support

  • Chrome: 146.
  • Edge: 146.
  • Firefox: not supported.
  • Safari: 26.

Source

Les registres d'éléments personnalisés à portée limitée permettent aux développeurs Web d'utiliser des modèles importants. Vous pouvez désormais utiliser plusieurs bibliothèques d'éléments personnalisés, développées indépendamment par plusieurs équipes, ou plusieurs versions de la même bibliothèque côte à côte.

Deux boutons avec un style très différent.

Qu'est-ce qu'un registre d'éléments personnalisés de portée ?

Aujourd'hui, chaque définition d'élément personnalisé sur une page Web réside dans un seul registre partagé à l'adresse window.customElements. Cela signifie que si deux bibliothèques différentes tentent de définir un élément personnalisé avec le même nom de balise, comme <my-button>, une erreur sera générée et la page sera interrompue. Il s'agit d'un problème important dans le monde réel. Les grandes applications qui composent leurs interfaces utilisateur à partir de plusieurs équipes, systèmes de conception ou micro-frontaux peuvent facilement rencontrer des conflits de noms. Les registres d'éléments personnalisés à portée limitée résolvent ce problème en vous permettant de créer des registres indépendants. Chaque registre conserve son propre ensemble de définitions d'éléments personnalisés, complètement isolé du registre global et des autres registres.

Créer un registre

Au lieu de définir chaque élément personnalisé dans le registre window.customElements global :

  1. Créez un registre en appelant new CustomElementRegistry().
  2. Attribuez un champ d'application spécifique à votre nouveau registre (consultez "Définir le champ d'application de votre registre").
  3. Définissez les éléments qui seront inclus dans le nouveau registre.

Ensuite, lorsqu'un élément personnalisé est utilisé, le navigateur recherche la définition de l'élément dans le registre associé, qui n'est pas nécessairement le registre global. Cela signifie que différentes parties de votre page peuvent utiliser des ensembles de définitions d'éléments personnalisés entièrement différents.

Définir le champ d'application de votre registre

Un registre d'éléments personnalisés peut être limité à un document, à une racine fantôme ou à un élément individuel.

Définir le champ d'application sur une racine fantôme

Pour définir le champ d'application d'un nouveau registre sur une racine fantôme, utilisez l'option customElementRegistry lorsque vous appelez la méthode attachShadow(). Tous les éléments personnalisés qui se trouvent dans cette racine fantôme utiliseront désormais la définition qui se trouve dans le registre à portée correspondante :

// 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 déclaratif

Utilisez l'attribut shadowrootcustomelementregistry sur un élément <template> pour indiquer au navigateur que la racine fantôme résultante utilise un registre à portée limitée plutôt que le registre global :

<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);

Comme le montre l'exemple, l'attribut réserve de l'espace pour le registre d'éléments personnalisés, et l'utilisateur doit définir et initialiser le registre pour la portée racine fantôme à un document déconnecté.

Vous pouvez également définir le champ d'application d'un registre sur un document, tel que celui créé par document.implementation.createHTMLDocument(). Cela vous permet de cloner des éléments <template> et de manipuler des documents hors écran, chacun avec son propre ensemble isolé de définitions de composants. Pour ce faire, utilisez la méthode 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>';

Définir le champ d'application sur un élément individuel

Vous pouvez également associer un registre directement à un élément et à son sous-arbre en transmettant l'option customElementRegistry à document.createElement(). L'élément et ses descendants seront résolus par rapport à ce registre, quelle que soit la partie du DOM dans laquelle ils sont insérés par la suite :

// 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>';

En savoir plus

Pour en savoir plus, consultez la démonstration Edge et son code source, ainsi que l'article de référence MDN sur CustomElementRegistry.

Les registres d'éléments personnalisés à portée limitée sont désormais activés par défaut dans Microsoft Edge et Chrome, ainsi que dans d'autres navigateurs basés sur Chromium, grâce à notre collaboration dans le cadre du projet Chromium.

Vous n'avez pas besoin d'activer de paramètre ni de vous inscrire à un test d'origine. Vous pouvez commencer à utiliser cette fonctionnalité dès aujourd'hui dans les navigateurs basés sur Chromium.

Si vous avez besoin que cette fonctionnalité soit implémentée dans d'autres navigateurs, ajoutez un pouce en l'air à la demande concernant les registres d'éléments personnalisés à portée limitée et laissez un commentaire avec vos cas d'utilisation et vos solutions de contournement.

Si vous rencontrez un bug avec l'implémentation de la fonctionnalité dans un navigateur basé sur Chromium, ouvrez un problème pour que nous puissions l'examiner sur crbug.com/new.

Nous espérons que les registres d'éléments personnalisés à portée limitée faciliteront l'utilisation des composants Web.