Custom Elements

Custom Elements, one of the most important spec under web components umbrella, enables web developer to define new types of HTMLElement, which can have it’s own markup(HTML), behavior(JS) and style(CSS). These newly created custom HTML tags can be reused as complex components in multiple websites and web apps.

Provide a way for web developers to build their own, full-featured DOM elements.

Table of Content

  1. Registration and Definition
  2. Imperative Usage
  3. Adding Behavior
  4. Inheriting native elements
  5. Browser Support
  6. Semantics


1. Registration and Definition

Custom Elements specification defines a programmatic way to define and register a custom element, using document.registerElement.

1
2
3
4
 var CustomElement = document.registerElement( 'custom-element' );
 var XLoader = document.registerElement( 'x-loader' );
 var GoogleAnalytics = document.registerElement( 'google-analytics' );
 var DropDown = document.registerElement( 'drop-down' );

document.registerElement takes 2 arguments. The first argument is custom element’s tag name. Whereas second argument is a object which holds the prototype object which defines feature set for that custom element. document.registerElement returns a constructor that can be used to create instances of custom element. There are other ways of instantiating elements, we will talk about them in a while.

Naming Rules

The tag name must contain at least one dash(-). Failing to do so will result in error and element won’t be created. For example, <x-loader>, <my-app>, <awesome-progress-bar> are all valid names, whereas <loader>, <component> are not. Any uppercase letter specified in tag name will be converted to lowercase.

2. Imperative Usage

As I mentioned above document.registerElement returns a constructor that can be used to create the instances of that particular custom element.

1
2
3
4
 var XLoader = document.registerElement( 'x-loader' );
 var xloader = new XLoader();

 document.body.appendChild( xloader );

You can also use document.createElement to instantiate the custom element, same as native HTML element.

1
2
3
4
 document.registerElement( 'google-analytics' );
 var googleAnalytics = document.createElement( 'google-analytics' );

 document.body.appendChild( googleAnalytics );

Above are two ways to instantiate element in JavaScript, you can also instantiate custom element in HTML, just use tag wherever you want in the document.

1
2
 <facebook-like-button></facebook-like-button>
 <facebook-share-button></facebook-share-button>

3. Adding Behavior

We learned how to define and use a custom element, lets learn how we can add features to these elements. Following codepen shows demo of <drop-down> custom element which is almost similar to one in bootstrap.

See the Pen Drop-down - Custom Element by Shridhar Deshmukh (@shree33) on CodePen.

Above HTML is only markup that you need to write to create drop-down like menu, without writing any javascript. The drop-down element knows how to handle the user interactions such as click, this is defined as behavior for the element while registering the element.

If you check the JavaScript in above codepen, you will notice that I have created a prototype object and passed it to document.registerElement. Prototype object is place where you can bundle tailored functionality of element by defining properties and methods.
I first created empty prototype object from HTMLElement, which will include feature set from HTMLElement in its prototype chain. Later I defined what should happen when the element gets created, using createCallback. Finally passed this prototype object to document.registerElement while registering the element. Once the element gets created, createdCallback is lifecycle method of custom element which will be called and click event listener will be added on button. There are other lifecycle methods that gets called during different phases of element’s life.

Lifecycle Callbacks

The callback methods are special methods that gets called when certain events happen on element. Following is list of lifecycle callback methods.

Callback method Element’s Life Phase
createdCallback an instance of the element is created
attachedCallback an instance was inserted into the document
detachedCallback an instance was removed from the document
attributeChangedCallback an attribute was added, removed, or updated

4. Inheriting native elements

Custom element can extend native HTML element’s features or features of other existing custom element. The custom element which extends native HTML elements called type extension custom element. To extend one of the native element we define new element which inherits the prototype of that native element and extends the tag name of that element.

1
2
3
4
 var SortableTable = document.registerElement( 'sortable-table', {
      prototype: Object.create(HTMLTableElement.prototype),
      extends: 'table'
 });

Above code block extends native <table> element, to do so it extends the table tag, also its prototype is based on HTMLTableElement and not the HTMLElement. By doing so you have extended APIs on top of basic <table> element’s features. To use this custom element, we just create the original tag element and specify custom tag name using is attribute.

1
 <table is="sortable-table"> </table>

5. Browser Support

Browser support of Custom Element is still in early days, currently supported by Chrome and Opera. Firefox by default it disabled, you can enable through dom.webcomponents.enabled preference in about:config. You can also check the updated browser support on caniuse.com. For other browsers you can use pollyfill library webcomponents.js.

6. Semantics

Custom elements has no special meaning at all,conveys similar amount of semantics as a HTML <div> and <span> element, but for semantics to be formally expressed, developers must convey the same using ARIA rules, states and properties. But type extension custom elements inherits the semantics of the element type it extends.

Conclusion

Custom Elements are true HTML elements, they come with many advantages such as

  • Encapsulation - Encapsulate internal details of component
  • Reusability - a component can be reused at multiple places, hence increase in productivity
  • Inheritance - inherits the properties and features from existing HTML elements

Comments