JavaScript Element customElementRegistry Property

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Limited availability
Instance property

What You’ll Learn

Element.customElementRegistry is a read-only instance property that returns the CustomElementRegistry tied to an element, or null. Learn how scoped registries work with shadow DOM, why the value is fixed after creation, and how to feature-detect—with five examples and try-it labs.

01

Kind

Instance property

02

Access

Read-only

03

Returns

CustomElementRegistry | null

04

Set when

Element is created

05

Mutable?

No (once set)

06

Status

Limited availability

Introduction

Most pages register custom elements on the global registry: window.customElements. Scoped custom element registries let a shadow tree (or other subtree) use its own registry so tag names do not collide with the rest of the page.

element.customElementRegistry tells you which registry that element will use when it is upgraded—or null if none was associated.

JavaScript
if ("customElementRegistry" in Element.prototype) {
  console.log(el.customElementRegistry); // CustomElementRegistry or null
}
💡
Beginner tip

Think: which dictionary of custom tags does this element belong to? Global page, or a scoped registry inside a component?

Understanding the Property

MDN: the customElementRegistry read-only property of the Element interface returns the CustomElementRegistry object associated with this element, or null if one has not been set.

An element’s registry is set when the element is created (for example via Document.createElement() with a customElementRegistry option, or when parsed in a context that already has a scoped registry). Once set to a CustomElementRegistry, it cannot be changed. That registry decides which custom element definitions are used when the element is upgraded.

  • Read-only — you cannot reassign the property later.
  • Nullablenull means no registry was associated.
  • Scoped APIs — often used with new CustomElementRegistry() and shadow roots.
  • Limited availability — not Baseline; feature-detect always (MDN).

📝 Syntax

JavaScript
customElementRegistry

Value

A CustomElementRegistry object, or null.

ItemDetail
TypeCustomElementRegistry | null
AccessRead-only
Global registrywindow.customElements
Scoped registrynew CustomElementRegistry()
⚠️
Feature-detect first

Support for reading Element.customElementRegistry (and creating scoped registries) is still rolling out. Check "customElementRegistry" in Element.prototype before production use.

📋 MDN Scoped Registry Example

MDN creates a scoped registry, attaches it to a shadow root, then confirms a child element reports the same registry:

JavaScript
const myRegistry = new CustomElementRegistry();
myRegistry.define(
  "my-element",
  class extends HTMLElement {
    connectedCallback() {
      this.textContent = "Hello from scoped registry!";
    }
  },
);

const host = document.createElement("div");
document.body.appendChild(host);
const shadow = host.attachShadow({
  mode: "open",
  customElementRegistry: myRegistry,
});
shadow.innerHTML = "<my-element></my-element>";

const el = shadow.querySelector("my-element");
console.log(el.customElementRegistry === myRegistry); // true

Related learning: window.customElements, Document.customElementRegistry, ShadowRoot.customElementRegistry, and currentCSSZoom.

⚡ Quick Reference

GoalCode / note
Read registryel.customElementRegistry
Feature-detect"customElementRegistry" in Element.prototype
Global registrywindow.customElements
Scoped shadowattachShadow({ customElementRegistry })
MDN statusLimited availability (not Baseline)

🔍 At a Glance

Four facts about Element.customElementRegistry.

Kind
get only

Instance

Type
registry | null

Or null

Use
scoped CE

Web Components

Support
limited

Not Baseline

Examples Gallery

Examples follow MDN Element: customElementRegistry. Labs feature-detect so unsupported browsers show a clear message.

📚 Getting Started

Feature-detect, then verify a scoped shadow registry.

Example 1 — Feature-Detect the Property

Check whether the browser exposes Element.customElementRegistry.

JavaScript
console.log("customElementRegistry" in Element.prototype);
Try It Yourself

How It Works

If this is false, skip scoped-registry code paths and fall back to the global customElements API.

Example 2 — Scoped Registry Matches the Element

MDN shape: shadow root with a custom registry; the child reports the same object.

JavaScript
const myRegistry = new CustomElementRegistry();
myRegistry.define("my-element", class extends HTMLElement {});
const host = document.createElement("div");
document.body.appendChild(host);
const shadow = host.attachShadow({
  mode: "open",
  customElementRegistry: myRegistry,
});
shadow.innerHTML = "<my-element></my-element>";
const el = shadow.querySelector("my-element");
console.log(el.customElementRegistry === myRegistry); // true
Try It Yourself

How It Works

Parsing <my-element> inside that shadow tree associates the element with myRegistry, so the identity check succeeds.

📈 Global Compare, Null Check & Snapshot

Contrast scoped vs global registries, then summarize support.

Example 3 — Scoped Registry Is Not the Global One

Confirm a scoped registry is a different object from window.customElements.

JavaScript
const myRegistry = new CustomElementRegistry();
console.log({
  sameAsGlobal: myRegistry === window.customElements,
  isRegistry: myRegistry instanceof CustomElementRegistry
});
Try It Yourself

How It Works

Scoped registries are separate dictionaries. Definitions on one do not automatically appear on the other.

Example 4 — Handle null Safely

Always null-check before calling registry methods.

JavaScript
const el = document.createElement("div");
const reg = el.customElementRegistry;
console.log(reg === null ? "null" : "has registry");
Try It Yourself

How It Works

Some contexts associate the global registry at creation time; others leave null. Treat both cases as valid and branch carefully.

Example 5 — Support Snapshot

Feature-detect and remember the rules.

JavaScript
console.log({
  supported: "customElementRegistry" in Element.prototype,
  returns: "CustomElementRegistry | null",
  tip: "Set at creation; immutable once set; use for scoped CE",
  status: "Limited availability (not Baseline) — MDN"
});
Try It Yourself

How It Works

Use this property when you need to inspect or reason about which custom element registry owns an element in a scoped setup.

🚀 Common Use Cases

  • Confirming a shadow tree is using your scoped CustomElementRegistry.
  • Debugging why a custom tag upgraded with unexpected definitions.
  • Building libraries that isolate tag names per component package.
  • Teaching the difference between global customElements and scoped registries.
  • Feature-detecting before shipping scoped-registry code paths.

🔧 How It Works

1

A registry is chosen at creation

From createElement options or a scoped parsing context.

Create
2

The association is stored on the element

Readable via customElementRegistry; not reassignable.

Bind
3

Upgrades use that registry

Definitions come from the associated CustomElementRegistry.

Upgrade
4

You can inspect the link

Compare with your scoped registry object for debugging.

📝 Notes

  • Not Deprecated, Experimental, or Non-standard on MDN/BCD (Limited availability / not Baseline).
  • Read-only — once a registry is set, it cannot be changed.
  • Feature-detect; Firefox may require a preference flag for scoped registries.
  • Related: currentCSSZoom, elementTiming, EventTarget, JavaScript hub.

Browser Support

Element.customElementRegistry has Limited availability on MDN (not Baseline). It is part of scoped custom element registries. Always feature-detect. Logos use the shared browser-image-sprite.png sprite from this project.

Limited availability

Element.customElementRegistry

Read-only CustomElementRegistry | null — which registry upgrades this element.

Limited Not Baseline
Google Chrome 146+
Yes
Microsoft Edge 146+ (Chromium)
Yes
Mozilla Firefox 150+ behind preference flag
Partial
Apple Safari 26+
Yes
Opera Follow Chromium (scoped CE)
Yes
Internet Explorer Not supported
No
customElementRegistry Limited

Bottom line: Use Element.customElementRegistry to inspect scoped registries. Feature-detect first. Prefer global window.customElements when scoped APIs are missing.

Conclusion

customElementRegistry answers a focused Web Components question: which CustomElementRegistry owns this element? It is set at creation, stays fixed, and unlocks scoped registries in shadow trees—with Limited availability, so detect before you depend on it.

Continue with elementTiming, currentCSSZoom, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Feature-detect before using scoped registries
  • Pass customElementRegistry when attaching shadow roots
  • Compare with === to verify the expected registry
  • Null-check before calling registry methods
  • Keep a global-customElements fallback

❌ Don’t

  • Assign to customElementRegistry (read-only)
  • Assume every browser supports scoped registries
  • Expect scoped definitions to appear on window.customElements
  • Skip identity checks when debugging upgrades
  • Confuse this with registering via customElements.define alone

Key Takeaways

Knowledge Unlocked

Five things to remember about customElementRegistry

Read-only registry link—set at creation, used for scoped custom elements.

5
Core concepts
📝 02

Registry

or null

Type
🔍 03

Scoped CE

shadow trees

Use
04

Limited

not Baseline

Status
🎯 05

Detect first

fallback ready

Tip

❓ Frequently Asked Questions

The CustomElementRegistry associated with the element, or null if none has been set.
No. MDN/BCD do not mark Element.customElementRegistry as Deprecated, Experimental, or Non-standard. It has Limited availability (not Baseline)—always feature-detect.
No. It is a read-only instance property. Once a CustomElementRegistry is set on the element, it cannot be changed.
When the element is created—for example Document.createElement() with a customElementRegistry option, or when the element is parsed inside a context that already uses a scoped registry (such as a shadow root).
window.customElements is the global registry. Element.customElementRegistry can point at that global registry or at a scoped CustomElementRegistry used only in a subtree (often a shadow tree).
So different components can define the same custom tag name without colliding in the global customElements registry.
Did you know?

Scoped registries exist so two libraries can both define <my-button> without fighting over the single global customElements map—each shadow tree can keep its own definitions.

Next: elementTiming

Learn how to label elements for PerformanceElementTiming observation.

elementTiming →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful