Web Components
Custom Elements
A set of JavaScript APIs that allow you to define custom elements and their behavior, which can then be used as desired in your user interface.
Types of Custom Elements
There are two types of custom element:
- Customized built-in elements inherit from standard HTML elements such as
HTMLImageElement
orHTMLParagraphElement
. Their implementation customizes the behavior of the standard element. - Autonomous custom elements inherit from the HTML element base class
HTMLElement
. Need to implement their behavior from scratch.
A custom element is implemented as a class which extends HTMLElement
(in the case of autonomous elements) or the interface to be customized customized (in the case of customized built-in elements).
JavaScript | |
---|---|
Registering & Using Custom Elements
To make a custom element available in a page, call the define()
method of Window.customElements
.
The define()
method takes the following arguments:
name
: The name of the element. This must start with a lowercase letter, contain a hyphen, and satisfy certain other rules listed in the specification's definition of a valid name.constructor
: The custom element's constructor function.options
: Only included for customized built-in elements, this is an object containing a single property extends, which is a string naming the built-in element to extend.
JavaScript | |
---|---|
HTML | |
---|---|
Custom Elements Lifecycle Callbacks
Once the custom element is registered, the browser will call certain methods of the class when code in the page interacts with the custom element.
By providing an implementation of these methods, which the specification calls lifecycle callbacks, it's possible to run code in response to these events.
Custom element lifecycle callbacks include:
connectedCallback()
: called each time the element is added to the document. The specification recommends that, as far as possible, developers should implement custom element setup in this callback rather than the constructor.disconnectedCallback()
: called each time the element is removed from the document.adoptedCallback()
: called each time the element is moved to a new document.attributeChangedCallback(name, oldValue, newValue)
: called when attributes are changed, added, removed, or replaced.
Shadow DOM
THe Shadow DOM allows to attach a DOM tree to an element, and have the internals of this tree hidden from JavaScript and CSS running in the page.
The shadow DOM tree starts with a shadow root, underneath which it's possible to attach any element, in the same way as the normal DOM.
Terminology:
- Shadow host: The regular DOM node that the shadow DOM is attached to.
- Shadow tree: The DOM tree inside the shadow DOM.
- Shadow boundary: the place where the shadow DOM ends, and the regular DOM begins.
- Shadow root: The root node of the shadow tree.
Creating a Shadow DOM
JavaScript | |
---|---|
Note:
{mode: "open"}
allows accessing the shadow DOM from the root nodeshadowDom
property. The "close" mode does not expose this property.
JavaScript & CSS Encapsulation
The JavaScript and CSS defined outside the shadow DOM do not have effect inside. To style a shadow dom there are two possibilities:
- defining a
CSSStylesheet
and assigning it to theShadowRoot: adoptedStyleSheets
- adding a
<style>
element in a<template>
element's declaration.
HTML | |
---|---|
<template>
and <slot>
The <template>
element
To reuse the same markup structures repeatedly on a web page, it makes sense to use some kind of a template rather than repeating the same structure over and over again.
The HTML <template>
and its contents are not rendered in the DOM, but it can still be referenced using JavaScript.
JavaScript | |
---|---|
Templates & Custom Elements
Templates are useful on their own, but they work even better with web components.
Since the template is added to a shadow DOM, it's possible to include styling information inside the template in a <style>
element, which is then encapsulated inside the custom element.
HTML | |
---|---|
JavaScript | |
---|---|
The <slot>
element
It possible to display different content in each element instance in a nice declarative way using the <slot>
element.
Slots are identified by their name attribute, and allow to define placeholders in the template that can be filled with any markup fragment when the element is used in the markup.