Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1131495 of Custom Elements

  • Revision slug: Web/Web_Components/Custom_Elements
  • Revision title: Custom Elements
  • Revision id: 1131495
  • Created:
  • Creator: teoli
  • Is current revision? No
  • Comment

Revision Content

{{SeeCompatTable}}

Custom Elements is a capability for creating your own custom HTML elements. They can have their own scripted behavior and CSS styling. They are a part of web components, but can also be used by themselves.

Note: Custom elements have only recently stabilized, and parts of MDN still contain documentation for outdated APIs from old specification drafts.

You might wonder why this new custom elements capability was created, because you could already create a tag name like <mytag> and style it with CSS, and use scripting to attach behaviors to it. One of the reasons to use custom elements is that you can use lifecycle reactions, which enables you to attach behaviors to different parts of the new element's "lifecycle." For example, you can attach a certain behavior when the element is inserted into the DOM ("connected"), and a different behavior when it is removed from the DOM ("disconnected"), or when its attributes change.

The key enabler of v1 custom elements is the {{domxref("CustomElementRegistry.define()")}} method. You can use this method to define a new custom element. The new element uses the class you supply for any instances, instead of the default {{domxref("HTMLUnknownElement")}}. You can also base a custom element on a native element like <button>, by using the syntax <button is="my-button">; these are called customized built-in elements.

Custom element reactions

Custom elements have the following reactions that govern how they behave:

constructor()
Called when the element is created or upgraded
connectedCallback()
Called when the element is inserted into a document, including into a shadow tree
disconnectedCallback()
Called when the element is removed from a document
attributeChangedCallback(attributeName, oldValue, newValue, namespace)
Called when an attribute is changed, appended, removed, or replaced on the element
adoptedCallback(oldDocument, newDocument)
Called when the element is adopted into a new document

Example

Custom elements require using the class syntax introduced in modern versions of JavaScript.

HTML file:

If nothing appeared below, then your browser is not supporting Custom Elements.
<x-product data-name="Ruby" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/ruby.png" data-url="https://example.com/1"></x-product>
<x-product data-name="JavaScript" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/javascript.png" data-url="https://example.com/2"></x-product>
<x-product data-name="Python" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/python.png" data-url="https://example.com/3"></x-product>

JS file:

// Create a class for the element
class XProduct extends HTMLElement {
  constructor() {
    // Create a shadow root
    var shadow = this.createShadowRoot();

    // Create a standard img element and set it's attributes.
    var img = document.createElement('img');
    img.alt = this.getAttribute('data-name');
    img.src = this.getAttribute('data-img');
    img.width = '150';
    img.height = '150';
    img.className = 'product-img';

    // Add the image to the shadow root.
    shadow.appendChild(img);

    // Add an event listener to the image.
    img.addEventListener('click', () => {
      window.location = this.getAttribute('data-url');
    });

    // Create a link to the product.
    var link = document.createElement('a');
    link.innerText = this.getAttribute('data-name');
    link.href = this.getAttribute('data-url');
    link.className = 'product-name';

    // Add the link to the shadow root.
    shadow.appendChild(link);
  }
}

// Define the new element
customElements.define('x-product', XProduct);

CSS file:

body {
  background: #F7F7F7;
}

x-product {
  display: inline-block;
  float: left;
  margin: 0.5em;
  border-radius: 3px;
  background: #FFF;
  box-shadow: 0 1px 3px rgba(0,0,0,0.25);
  font-family: Helvetica, arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

x-product::slotted(.product-img) {
  cursor: pointer;
  background: #FFF;
  margin: 0.5em;
}

x-product::slotted(.product-name) {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #08C;
  border-top: 1px solid #EEE;
  font-weight: bold;
  padding: 0.75em 0;
}

Below is the live example of the above:

{{ EmbedLiveSample('Example', '1500', '250', '', 'Web/Web_Components/Custom_Elements') }}

Specifications

Custom Elements is defined in the following specification:

Specification Status Comment
The HTML Standard: Custom elements LS  

Resources

Revision Source

<p>{{SeeCompatTable}}</p>

<p>Custom Elements is a capability for creating your own custom HTML <a href="/en-US/docs/Glossary/Element">elements</a>. They can have their own scripted behavior and CSS styling. They are a part of <a href="/en-US/docs/Web/Web_Components">web components</a>, but can also be used by themselves.</p>

<div class="note">
<p><strong>Note:</strong> Custom elements have only recently stabilized, and parts of MDN still contain documentation for outdated APIs from old specification drafts.</p>
</div>

<p>You might wonder why this new custom elements capability was created, because you could already create a tag name like <code>&lt;mytag&gt;</code> and style it with CSS, and use scripting to attach behaviors to it. One of the reasons to use custom elements is that you can use <em>lifecycle reactions</em>, which enables you to attach behaviors to different parts of the new element's "lifecycle." For example, you can attach a certain behavior when the element is inserted into the DOM ("connected"), and a different behavior when it is removed from the DOM ("disconnected"), or when its attributes change.</p>

<p>The key enabler of v1 custom elements is the {{domxref("CustomElementRegistry.define()")}} method. You can use this method to define a new custom element. The new element uses the class you supply for any instances, instead of the default {{domxref("HTMLUnknownElement")}}. You can also base a custom element on a native element like <code>&lt;button&gt;</code>, by using the syntax <code>&lt;button is="my-button"&gt;</code>; these are called <em>customized built-in elements</em>.</p>

<h2 id="Custom_element_reactions">Custom element reactions</h2>

<p>Custom elements have the following reactions that govern how they behave:</p>

<dl>
 <dt>constructor()</dt>
 <dd>Called when the element is created or upgraded</dd>
 <dt>connectedCallback()</dt>
 <dd>Called when the element is inserted into a document, including into a shadow tree</dd>
 <dt>disconnectedCallback()</dt>
 <dd>Called when the element is removed from a document</dd>
 <dt>attributeChangedCallback(attributeName, oldValue, newValue, namespace)</dt>
 <dd>Called when an attribute is changed, appended, removed, or replaced on the element</dd>
 <dt>adoptedCallback(oldDocument, newDocument)</dt>
 <dd>Called when the element is adopted into a new document</dd>
</dl>

<h2 id="Example">Example</h2>

<p>Custom elements require using the <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes"><code>class</code> syntax</a> introduced in modern versions of JavaScript.</p>

<p>HTML file:</p>

<pre class="brush: html">
If nothing appeared below, then your browser is not supporting Custom Elements.
&lt;x-product data-name="Ruby" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/ruby.png" data-url="https://example.com/1"&gt;&lt;/x-product&gt;
&lt;x-product data-name="JavaScript" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/javascript.png" data-url="https://example.com/2"&gt;&lt;/x-product&gt;
&lt;x-product data-name="Python" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/python.png" data-url="https://example.com/3"&gt;&lt;/x-product&gt;</pre>

<p>JS file:</p>

<pre class="brush: js">
// Create a class for the element
class XProduct extends HTMLElement {
  constructor() {
    // Create a shadow root
    var shadow = this.createShadowRoot();

    // Create a standard img element and set it's attributes.
    var img = document.createElement('img');
    img.alt = this.getAttribute('data-name');
    img.src = this.getAttribute('data-img');
    img.width = '150';
    img.height = '150';
    img.className = 'product-img';

    // Add the image to the shadow root.
    shadow.appendChild(img);

    // Add an event listener to the image.
    img.addEventListener('click', () =&gt; {
      window.location = this.getAttribute('data-url');
    });

    // Create a link to the product.
    var link = document.createElement('a');
    link.innerText = this.getAttribute('data-name');
    link.href = this.getAttribute('data-url');
    link.className = 'product-name';

    // Add the link to the shadow root.
    shadow.appendChild(link);
  }
}

// Define the new element
customElements.define('x-product', XProduct);
</pre>

<p>CSS file:</p>

<pre class="brush: css">
body {
&nbsp; background: #F7F7F7;
}

x-product {
&nbsp; display: inline-block;
&nbsp; float: left;
&nbsp; margin: 0.5em;
&nbsp; border-radius: 3px;
&nbsp; background: #FFF;
&nbsp; box-shadow: 0 1px 3px rgba(0,0,0,0.25);
&nbsp; font-family: Helvetica, arial, sans-serif;
&nbsp; -webkit-font-smoothing: antialiased;
}

x-product::slotted(.product-img) {
&nbsp; cursor: pointer;
&nbsp; background: #FFF;
&nbsp; margin: 0.5em;
}

x-product::slotted(.product-name) {
&nbsp; display: block;
&nbsp; text-align: center;
&nbsp; text-decoration: none;
&nbsp; color: #08C;
&nbsp; border-top: 1px solid #EEE;
&nbsp; font-weight: bold;
&nbsp; padding: 0.75em 0;
}
</pre>

<p>Below is the live example of the above:</p>

<p>{{ EmbedLiveSample('Example', '1500', '250', '', 'Web/Web_Components/Custom_Elements') }}</p>

<h2 id="Specifications">Specifications</h2>

<p>Custom Elements is defined in the following specification:</p>

<table class="spec-table standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td><a href="https://html.spec.whatwg.org/multipage/scripting.html#custom-elements">The HTML Standard: Custom elements</a></td>
   <td>LS</td>
   <td>&nbsp;</td>
  </tr>
 </tbody>
</table>

<h2 id="Resources">Resources</h2>

<ul>
 <li><a href="https://developers.google.com/web/fundamentals/primers/customelements/">Custom elements v1: reusable web components - Google Developers tutorial</a></li>
</ul>
Revert to this revision