is

Extend native HTML elements with custom behavior via customized built-in elements. Inherits all native semantics, accessibility, and form participation for free.

Overview

The is attribute creates customized built-in elements — native HTML elements enhanced with custom JavaScript behavior. Unlike autonomous custom elements (e.g., <my-component>), customized built-ins inherit all native behavior: semantics, accessibility, form participation, and default styles.

The syntax is <element is="custom-name">, where the custom element class extends the native element's interface (e.g., HTMLButtonElement, HTMLInputElement).

Usage

Add the is attribute to a native element to activate the custom behavior registered for that name.

<!-- Use a customized built-in button --> <button is="confirm-button">Delete Account</button> <!-- The element is still a <button> with all native behavior: - Form participation - Keyboard activation (Enter/Space) - Default button styling - Screen reader announces "button" But with custom behavior added by the class -->

Registration

The custom element class must extend the specific element interface, and the define() call must include the extends option.

<script> class ConfirmButton extends HTMLButtonElement { connectedCallback() { this.addEventListener('click', (e) => { if (!confirm(`Are you sure you want to: ${this.textContent}?`)) { e.preventDefault(); e.stopPropagation(); } }); } } // Third argument { extends } tells the registry which element is being extended customElements.define('confirm-button', ConfirmButton, { extends: 'button' }); </script>

Example: Auto-Format Input

A text input that automatically formats phone numbers as the user types. It inherits all native input behavior — form submission, validation, labels, autofill.

<script> class AutoFormatInput extends HTMLInputElement { connectedCallback() { this.addEventListener('input', () => { // Auto-format as phone number: (123) 456-7890 const digits = this.value.replace(/\D/g, '').slice(0, 10); if (digits.length >= 6) { this.value = `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`; } else if (digits.length >= 3) { this.value = `(${digits.slice(0,3)}) ${digits.slice(3)}`; } }); } } customElements.define('auto-format-input', AutoFormatInput, { extends: 'input' }); </script> <label for="phone">Phone</label> <input is="auto-format-input" type="tel" id="phone" name="phone" />

Customized vs Autonomous

There are two types of custom elements. The is attribute is for the customized built-in type.

<!-- Customized built-in: extends <button>, inherits everything --> <button is="fancy-button">Click Me</button> <!-- Autonomous custom element: starts from scratch --> <fancy-button>Click Me</fancy-button>
FeatureCustomized Built-in (is)Autonomous (<my-el>)
Syntax<button is="x"><my-button>
ExtendsSpecific element interfaceHTMLElement
Native semanticsInheritedMust be added manually
Form participationInheritedRequires ElementInternals
Default stylesInheritedNone
Safari supportNoYes
Browser supportChrome, Firefox, EdgeAll modern browsers

Accessibility

  • The primary advantage of customized built-in elements is accessibility. A <button is="fancy-button"> is announced as "button" by screen readers, participates in tab order, and responds to Enter and Space — with zero extra work.
  • An autonomous <fancy-button> would need role="button", tabindex="0", and keyboard event handlers to achieve the same accessibility.
  • For form controls, the is approach inherits native validation, labels, and error messages automatically.

Limitations

  • Safari does not support the is attribute. This is the most significant limitation. Safari's WebKit team has explicitly declined to implement it, citing architectural concerns. This makes customized built-ins unreliable for production use without a polyfill.
  • A polyfill exists but adds bundle size and complexity. It works by detecting is attributes and manually upgrading elements.
  • Each customized built-in can only extend one specific element type. A class extending HTMLButtonElement cannot be used on an <input>.
  • Server-rendered HTML with is attributes works in Chrome and Firefox before JavaScript loads (the native element renders normally). In Safari, the is attribute is simply ignored.
  • Due to the Safari limitation, the web platform has largely moved toward autonomous custom elements instead. Most component libraries use <my-element> syntax for universal compatibility.

See Also

  • Web Components — VB's custom elements (using autonomous syntax for browser compatibility)
  • tabindex — manage focus order for custom interactive elements
  • disabled — inherited by customized built-in form controls