Need a reusable piece of UI that behaves like an HTML element? Custom Elements let you give an author-created tag its own class and behavior. The tag can then appear in a page alongside familiar elements such as buttons and inputs. A custom element does not, by itself, hide its internal DOM; Shadow DOM addresses that separate concern. section 1.1 section 8.1
A small element starts with a few browser rules:
- Put a dash in the tag name, such as <progress-bar>. The dash distinguishes a custom-element name from a native tag name; a shared prefix can also identify a family of components. section 2.2
- Create a JavaScript class that extends HTMLElement, then register its name and class with customElements.define(). Check customElements.get() first if the registration code might run again: defining the same name twice throws an error. section 2.3
- Add connectedCallback() for work that should happen when the element joins the DOM. Inside it, this refers to the element, so it can read attributes, create markup, and find its children. section 2.4 section 2.6
if (!customElements.get('my-custom-tag')) {
customElements.define('my-custom-tag', class extends HTMLElement {});
}
This short registration guard shows both the required HTMLElement subclass and the check that avoids a duplicate definition. section 2.3
Build a photo carousel
Place a <wcia-photo-carousel> tag on the page with title, author, and comma-separated photos attributes. Its connectedCallback() reads those values, creates a heading, image area, and back and forward buttons, then shows the first image. Button listeners change the current photo index and wrap around at either end. CSS styles the tag and its children. This is an ordinary page element with custom behavior, not just an unfamiliar tag name. section 2.6
Registration and connection are different moments. Defining a class does not put an element on the page. Creating one with document.createElement() runs its constructor; adding it to the document triggers connectedCallback(). If you write a constructor in the subclass, call super() first. Keep DOM-content setup in connectedCallback() rather than assuming the constructor can create children or read markup attributes. section 4.2
Custom tags can accept click listeners and attributes like other elements. For changing attributes, attributeChangedCallback() provides another lifecycle hook; a component can also expose methods and properties. JavaScript modules can organize components that depend on one another. These examples use the Custom Elements v1 API: older references to document.registerElement() describe an earlier approach. Browser support in the described period varied; a Custom Elements polyfill could cover unsupported browsers, while older JavaScript syntax support remained a separate issue. section 2.5 section 3.7 section 5.2 section 2.7

