Loading...

HTML Custom Elements

HTML Custom Elements are part of the Web Components specification and enable developers to define new HTML tags with custom behavior and appearance. Just like organizing a library with labeled sections or writing personalized letters for unique recipients, custom elements let you create reusable, encapsulated HTML components that can be dropped into any project. These elements follow standard HTML syntax but carry the power of being fully customizable, allowing you to define their structure, style, and logic.
They are especially valuable when working on projects like a portfolio website (to encapsulate project cards), blogs (for comment sections), e-commerce platforms (product listings), news sites (article cards), or social platforms (user profile widgets). Rather than rewriting the same HTML and JavaScript repeatedly, you define a custom element once and use it everywhere with ease.
In this tutorial, you’ll learn what custom elements are, how they’re created and used, and why they matter in modern frontend development. You’ll see examples ranging from simple definitions to real-world applications, understand best practices, and discover pitfalls to avoid. Whether you're building a scalable design system or modular UI components, HTML Custom Elements give you the power to build smarter and cleaner websites.

Basic Example

html
HTML Code
<!-- Define and use a simple custom element -->

<script>
class MyGreeting extends HTMLElement {
connectedCallback() {
this.innerHTML = "<p>Hello from a custom element!</p>";
}
}
customElements.define('my-greeting', MyGreeting);
</script>

<my-greeting></my-greeting>

Let’s break this down. The <script> section defines a new custom HTML element named <my-greeting>. First, we create a class MyGreeting that extends HTMLElement, the base class for all custom elements. This tells the browser we're creating a new type of HTML element with custom behavior.
Inside the class, we define the connectedCallback() method. This is one of the lifecycle callbacks and gets called automatically whenever the element is inserted into the DOM. Think of this like decorating a room the moment you enter it—this is your chance to set up the contents, event listeners, or styling.
In this case, this.innerHTML is used to inject a simple <p> tag with a message. After defining the class, customElements.define('my-greeting', MyGreeting) tells the browser that whenever it sees <my-greeting> in the markup, it should instantiate this class.
Finally, the element <my-greeting></my-greeting> in the HTML automatically calls the connectedCallback, and the greeting message is rendered. This small example encapsulates a powerful concept: creating reusable, self-contained components without frameworks. Beginners often ask if JavaScript frameworks are required—no, this is pure JavaScript and works natively in modern browsers. It's a great foundation for scalable UIs.

Practical Example

html
HTML Code
<!-- Custom element for a user profile card in a social platform -->

<script>
class UserProfile extends HTMLElement {
connectedCallback() {
const name = this.getAttribute('name') || "Anonymous";
const role = this.getAttribute('role') || "User";
this.innerHTML = `
<div class="card">
<h2>${name}</h2>
<p>Role: ${role}</p>
</div>`;
}
}
customElements.define('user-profile', UserProfile);
</script>

<user-profile name="Jane Doe" role="Moderator"></user-profile>

Best practices and common mistakes when working with HTML Custom Elements include key coding disciplines to ensure your components are maintainable, semantic, and performant.
Best Practices:

  1. Use Semantic HTML: Inside custom elements, use proper tags like <article>, <header>, <section>, etc., to enhance accessibility and SEO.
  2. Encapsulate Structure: Keep your element logic self-contained. Define styles and behaviors within the component, not externally unless scoped.
  3. Provide Default States: Always include fallback content or default values, as shown in the UserProfile example (Anonymous, User).
  4. Ensure Accessibility: Add ARIA labels and roles when necessary so assistive technologies can interpret your elements.
    Common Mistakes:

  5. Non-semantic Wrapping: Using <div>s excessively without meaningful structure hinders usability.

  6. Omitting Attributes: Failing to validate or default missing attributes can break UI or logic.
  7. Improper Nesting: Inserting custom elements in invalid HTML locations (like directly inside <ul>) can cause render issues.
  8. Not Handling Lifecycle Hooks: Ignoring lifecycle callbacks like disconnectedCallback() can lead to memory leaks.
    Debugging Tip: If your custom element isn't rendering, verify that customElements.define() has been called before the element is used. Check the browser console for registration errors or syntax issues.
    Practical Advice: Keep your custom element names hyphenated (e.g., user-profile) to avoid conflicts with built-in HTML elements. Avoid polluting the global namespace—use modules or scope where applicable.

📊 Quick Reference

Property/Method Description Example
customElements.define() Registers a new custom element customElements.define('my-tag', MyClass)
connectedCallback() Called when the element is inserted into DOM used to render HTML or add listeners
disconnectedCallback() Called when element is removed from DOM used to clean up timers, listeners
observedAttributes Specifies which attributes to watch static get observedAttributes() { return \['name'] }
attributeChangedCallback() Fires when observed attribute changes used to update content dynamically
HTMLElement Base class for all custom elements class MyElement extends HTMLElement

Summary and next steps:
HTML Custom Elements empower you to create reusable, encapsulated components using only native browser APIs. We’ve explored how to define and use them through examples like greeting tags and user profiles, and learned to harness lifecycle callbacks and attribute-based rendering.
These components integrate seamlessly with CSS for styling and JavaScript for logic or interactivity. For example, styling can be scoped using Shadow DOM (a next-level topic), and event listeners can be added for interactivity—enabling highly dynamic experiences without bloated frameworks.
As your next step, dive deeper into Shadow DOM, HTML Templates, and Slots, which expand the power of Custom Elements. These let you fully encapsulate styles and create content placeholders.
Recommended topics:

  • Styling Custom Elements with Shadow DOM
  • Using slots for content projection
  • Lifecycle hooks beyond connectedCallback
  • Integrating with frameworks like Lit or Stencil
    Continue building your own design systems using these tools. Think of Custom Elements as modular building blocks—just like rooms in a house—you can assemble to create beautiful, scalable architectures.

🧠 Test Your Knowledge

Ready to Start

Test Your Knowledge

Test your understanding of this topic with practical questions.

4
Questions
🎯
70%
To Pass
♾️
Time
🔄
Attempts

📝 Instructions

  • Read each question carefully
  • Select the best answer for each question
  • You can retake the quiz as many times as you want
  • Your progress will be shown at the top