How to get list of registered custom elements

Since custom elements is now part of the latest standard, I thought I'd share how to do this in 2017+:

Note: the document.registerElement function has been deprecated in favor of customElements.define().

customElements is defined as a global in window. There are three methods defined:

  1. define
  2. get
  3. whenDefined

get is the important one here. get takes a string of the element name and returns the constructor for the named custom element, or undefined if there is no custom element definition for the name.

So in 2017+ to check if an element has been registered do you:

const myElementExists = !!customElements.get('my-element');

I'm not sure if there's a way to get a list of defined elements however.


NOTE: this doesn't work in IE. See here for browser compatibility


There is a way to check whether an element was registered. Registered elements have their own constructors, while unregistered ones would use plain HTMLElement() for constructor (or HTMLUnknownElement() whether the name is not valid, but this is out of scope of the question):

document.registerElement('x-my-element');
document.createElement('x-my-element').constructor
//⇒ function x-my-element() { [native code] }
document.createElement('x-my-element-not-registered').constructor
//⇒ function HTMLElement() { [native code] }

That said, the checker might look like:

var isRegistered = function(name) {
  return document.createElement(name).constructor !== HTMLElement;
}

Or, with syntactic sugar:

String.prototype.isRegistered = function() { 
  return document.createElement(this).constructor !== HTMLElement; 
}
'x-my-element'.isRegistered()
//⇒ true
'xx-my-element'.isRegistered()
//⇒ false

The mostly careful version:

String.prototype.wasRegistered = function() { 
  switch(document.createElement(this).constructor) {
    case HTMLElement: return false; 
    case HTMLUnknownElement: return undefined; 
  }
  return true;
}
'x-my-element'.wasRegistered()
//⇒ true
'xx-my-element'.wasRegistered()
//⇒ false
'xx'.wasRegistered()
//⇒ undefined

There is no way to access a list of registered elements, AFAIK.

BTW, I still think that the try-catched registration (as proposed by @stephan-muller) suits your needs better.


EDIT (2021): This no longer works as /deep/ was removed a few years ago.


Combining a few of the above approaches you can iterate over everything in use and spit out a unique list of custom (and registered) elements:

function isRegistered(name) {
  return document.createElement(name).constructor.__proto__ !== window.HTMLElement;
}

var allElems = document.querySelectorAll('html /deep/ *');
var nodeNames = [].map.call(allElems, el => el.nodeName.toLowerCase())
                    .filter((value, index, self) => self.indexOf(value) === index)

console.log('all elements', nodeNames);
console.log('registered, custom elements', nodeNames.filter(isRegistered))

enter image description here