Skip to main content
Dublin Library

The Publishing Project

HTML Web Components

 

When evaluating web components for the blog, I also came around a different idea. Can we build web components that don't want to use shadow DOM? Would it make sense to do so?

Another element to look at is to build web components for some aspects of the blog using either bare bones web components that eschew the shadow DOM, or libraries like Lit, Wired Elements or Shoelace/Web Awesome.

The basic idea is this:

  1. Create a web component
  2. Insert the content in the component's light DOM
  3. Evaluate if styling is appropriate or not

Hand Written Web Components #

Most of the time when I see web components in a page, I see this:

<my-component></my-component>

Until this component initializes with the connectedCallback lifecycle callback there is not content displayed on the page. If the component is not initialized then nothing will display on the page.

Likewise, if we use shadow DOM or templates and the page is not initialized or the Javascript fails to load then there will be no content displayed on the page.

But what happens if we just load HTML inside the web component? Do we still need to initialize it via Javascript?

Asking the question Jeremy Keith has asked in his presentations about technology How well do web components fail?

Using the super-slider component from Eric Meyer's post, let's look at the element itself. Instead of leaving it bare we insert the children directly into the HTML, in the light DOM if you want, and use web component lifecycle methods to wire the necessary scripting.

The HTML looks similar to what we'd do instead of using a web component. We just wrap a web component

<super-slider unit="em" target=".preview h1">
	<label for="title-size">Title font size</label>
	<input id="title-size" type="range" min="0.5" max="4" step="0.1" value="2" />
</super-slider>

We define the custom element in Javascript using a class that extends the HTML element.

The constructor is optional, but I always use it to ensure proper inheritance from the parent.

In the connectedCallback we initialize the component and its children.

finally we match the Javascript with the custom element name using the define method of the CustomElementRegistry interface.

class superSlider extends HTMLElement {
	constructor() {
    super();
  }

	connectedCallback() {
    let targetEl = document.querySelector(this.getAttribute('target'));
    let unit = this.getAttribute('unit');
    let slider = this.querySelector('input[type="range"]');
    slider.addEventListener("input",(e) => {
      targetEl.style.setProperty('font-size', slider.value + unit);
    });
  }
}

customElements.define("super-slider",superSlider);

SO what's the difference between an element define like this and a traditional custom element?

It makes the page easier to understand, it provides a fallback in case the script fails to load and it provides a way to enhance the content without adding bloat to the page.

Whether you use this style of components or choose to use shadow DOM to hide content and styles inside the component, or even choose to skip web components altogether, is your choice based on what your project needs.

Edit on Github