Skip to content

Customized Built-ins

The Web Components spec defines two flavors of custom element:

FlavorExtendsRegistered asUsed in HTML
AutonomousHTMLElementcustomElements.define('x-btn', XBtn)<x-btn>
Customized built-ine.g. HTMLButtonElementcustomElements.define('x-btn', XBtn, { extends: 'button' })<button is="x-btn">

A customized built-in extends a specific HTML element class and declares which built-in it extends in the third argument to define:

class FancyButton extends HTMLButtonElement {
connectedCallback() {
this.style.background = '#4f46e5';
this.style.color = '#fff';
this.style.borderRadius = '6px';
this.style.padding = '.4rem 1rem';
this.style.border = 'none';
this.style.cursor = 'pointer';
}
}
customElements.define('fancy-button', FancyButton, { extends: 'button' });

In HTML, the is attribute activates the customized built-in on a standard element:

<button is="fancy-button">Click me</button>

The element is still a <button> — it inherits all the built-in semantics (focusable, submits forms, responds to disabled) plus your custom behavior.

Safari does not support customized built-ins and has explicitly declined to implement them. This is a significant portability problem: a <button is="fancy-button"> will render as a plain unstyled button in Safari.

There are polyfills (such as @ungap/custom-elements), but they add weight and complexity.

<!-- This renders correctly in Chrome/Firefox but NOT in Safari: -->
<button is="fancy-button">Safari renders this as a plain button</button>

Autonomous custom elements (extends HTMLElement) are fully supported everywhere. For the button example, an equivalent autonomous element:

class XButton extends HTMLElement {
connectedCallback() {
this.innerHTML =
'<button style="background:#4f46e5;color:#fff;border-radius:6px;' +
'padding:.4rem 1rem;border:none;cursor:pointer">' +
(this.textContent || 'Click me') + '</button>';
}
}
customElements.define('x-button', XButton);

You lose the automatic inheritance of native <button> semantics (you must add role="button" and keyboard handling manually), but you gain full cross-browser support.

The demo below uses an autonomous element — it works in every browser. The customized built-in syntax is shown for reference only.

Browser note: The customized built-in pattern (class extends HTMLButtonElement + <button is="...">) is not supported in Safari. Use autonomous elements (class extends HTMLElement) for portable, cross-browser Web Components.

How do you activate a customized built-in element in HTML?
Which third argument to customElements.define signals a customized built-in?
Which browser does NOT support customized built-in elements?