Can I enhance a custom element progressively?

posted on

Back to overview

Yes!

As already mentioned, you can create a custom element without JavaScript and select and style it in CSS. That means you can define default styles for your custom element and style elements in light DOM. As soon as the web component is defined, encapsulated styles within the component will be added on top.

the-message {
  display: block;
  border: 4px var(--border-style, solid) var(--border-color, currentColor);
  padding: 1em;
}
<the-message type="warning">
  A message to you, Rudy.
</the-message>

Click the “Define” button to define this undefined custom element and see how component styles enhance the default styling.

A message to you, Rudy.
class TheMessage extends HTMLElement {
  static observedAttributes = ["type", "text"];

  constructor() {
    super();

    this.attachShadow({ mode: "open" });
    this._attachStyles();

    const slot = document.createElement('slot')
    this.shadowRoot.appendChild(slot);
  }

  _attachStyles() {
    const style = document.createElement("style");
    style.textContent = `
      :host([type="warning"]) {
      --border-style: dotted;
      --border-color: orange;
      }
    `;

    this.shadowRoot.appendChild(style);
  }
}

Are you wondering where the background color is coming from? Keep reading! :)

The :defined pseudo-class

You can use the :defined pseudo-class to apply styles to a custom element only when it's (not) defined for even more control over progressive enhancement.

/* Applies only when the custom element is not defined */
the-message:not(:defined) {
  background-color: #e4fcff; /* light blue */
}

/* Applies only when the custom element is defined */
the-message:defined {
  background-color: #ffebcf; /* light orange */
}

Back to overview