Defining Custom Elements
Register elements with the customElements API.
Defining Custom Elements is a free JavaScript Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the JavaScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Are Custom Elements?
Custom elements let you define your own HTML tags backed by JavaScript classes. Instead of gluing together div soup, you create a reusable, self-contained component like <user-card>.
- They are part of the Web Components standard.
- They work natively in browsers, no framework required.
- A custom element name must contain a hyphen (e.g.
my-button).
The customElements Registry
The browser exposes a global registry at window.customElements. You register a new tag by calling customElements.define(name, constructor).
Once defined, every matching tag in the document is upgraded into an instance of your class.
// Register a tag named 'hello-world'
customElements.define('hello-world', HelloWorld);
// After this, every <hello-world> in the page
// becomes an instance of the HelloWorld class.Extending HTMLElement
A custom element is a class that extends HTMLElement. The base class gives your element all standard DOM capabilities (attributes, events, styling).
Always call super() first in the constructor so the element is properly initialized.
class HelloWorld extends HTMLElement {
constructor() {
super(); // required, sets up the element
}
}
customElements.define('hello-world', HelloWorld);Rendering Content
Inside the element you can set this.innerHTML or use DOM methods to build content. A common pattern is to render when the element is connected to the page.
class HelloWorld extends HTMLElement {
connectedCallback() {
this.innerHTML = '<p>Hello from a custom element!</p>';
}
}
customElements.define('hello-world', HelloWorld);Using the Element in HTML
After registration, use your tag just like any built-in element. You can place it directly in markup or create it with document.createElement.
// In HTML:
// <hello-world></hello-world>
// Or in JavaScript:
const el = document.createElement('hello-world');
document.body.appendChild(el);The Constructor's Rules
The constructor runs when an instance is created. There are strict rules:
- Call
super()first. - Do not inspect or add attributes/children here.
- Defer DOM work to
connectedCallback.
Use the constructor only for initial state and event listener setup.
class CounterButton extends HTMLElement {
constructor() {
super();
this.count = 0; // safe: just internal state
}
}
customElements.define('counter-button', CounterButton);Adding Behavior
Because your element is a real DOM node, you can attach event listeners and update its content in response to interaction.
class CounterButton extends HTMLElement {
constructor() {
super();
this.count = 0;
}
connectedCallback() {
this.textContent = 'Clicked 0 times';
this.addEventListener('click', () => {
this.count++;
this.textContent = 'Clicked ' + this.count + ' times';
});
}
}
customElements.define('counter-button', CounterButton);The Hyphen Requirement
Custom element names must include a dash. This guarantees they never clash with current or future built-in HTML elements.
my-widgetis valid.mywidgetis invalid and throws an error.- Names are case-insensitive but written lowercase.
// Valid:
customElements.define('app-header', AppHeader);
// Invalid - throws SyntaxError (no hyphen):
// customElements.define('appheader', AppHeader);whenDefined and get
Two useful registry methods:
customElements.get(name)returns the constructor, orundefinedif not registered.customElements.whenDefined(name)returns a Promise that resolves once the element is defined.
customElements.whenDefined('hello-world').then(() => {
console.log('hello-world is ready to use');
});
const Ctor = customElements.get('hello-world');Defining Only Once
Each name can be registered only once. Calling define with an already-used name throws. Guard against double registration in shared modules.
if (!customElements.get('hello-world')) {
customElements.define('hello-world', HelloWorld);
}Why Custom Elements Matter
Custom elements give you framework-agnostic, encapsulated, reusable UI. They:
- Standardize component reuse across any stack.
- Integrate with the browser's own lifecycle.
- Pair naturally with Shadow DOM and templates (covered later).
Quick Check
Test your understanding of defining custom elements.
Recap
You learned how to define custom elements:
customElements.define(name, class)registers a tag.- The class
extends HTMLElementand callssuper()first. - Names must include a hyphen.
- Render content in
connectedCallback, not the constructor. getandwhenDefinedhelp you check registration status.
Next, we explore the full lifecycle of a custom element.
Frequently asked questions
Is the “Defining Custom Elements” lesson free?
Yes — the full text of “Defining Custom Elements” is free to read here on the web, and the JavaScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the JavaScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “Defining Custom Elements”?
Register elements with the customElements API. You practise JavaScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start JavaScript Academy?
No prior experience is required. JavaScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Defining Custom Elements” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this JavaScript Academy lesson?
Yes. Every JavaScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Defining Custom Elements
- Lifecycle Callbacks
- Shadow DOM and Encapsulation
- Templates and Slots