Custom Elements
Defining custom HTML elements, lifecycle callbacks, and encapsulation.
Overview
Custom elements extend HTML with new tags.
Key Concepts
- CustomElementRegistry — Register new elements
- Lifecycle Callbacks — connected, disconnected, attribute changed
- Shadow DOM — Encapsulation
- Templates — Reusable markup
- Framework Agnostic — Work anywhere
Code Examples
<user-card name="John Doe" email="john@example.com" avatar="https://i.pravatar.cc/150?u=john">
</user-card>
<user-card name="Jane Smith" email="jane@example.com">
</user-card>
<script>
class UserCard extends HTMLElement {
static get observedAttributes() {
return ['name', 'email', 'avatar'];
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
render() {
const name = this.getAttribute('name') || 'Unknown';
const email = this.getAttribute('email') || '';
const avatar = this.getAttribute('avatar') || `https://ui-avatars.com/api/?name=${encodeURIComponent(name)}`;
this.shadowRoot.innerHTML = `
<style>
:host {
display: flex;
align-items: center;
padding: 16px;
border: 1px solid #ddd;
border-radius: 8px;
margin: 8px 0;
font-family: system-ui, sans-serif;
}
.avatar {
width: 60px;
height: 60px;
border-radius: 50%;
margin-right: 16px;
}
.info h3 {
margin: 0 0 4px 0;
font-size: 1.2rem;
}
.info p {
margin: 0;
color: #666;
}
</style>
<img class="avatar" src="${avatar}" alt="${name}">
<div class="info">
<h3>${name}</h3>
<p>${email}</p>
</div>
`;
}
}
customElements.define('user-card', UserCard);
</script>
Practice
Create a custom <notification-toast> element with auto-dismiss.