Web Components: The Basics


I learned how to use Web Components for a take-home coding challenge! Here's a small collection of useful information I gathered.

(I'm assuming you have a solid foundation of HTML/JavaScript knowledge.)

  1. tl;dr
  2. Hello World example code
  3. My implementation notes
  4. Web Components documentation on Mozilla Developer Network

The ColorPicker web component I made:

Background

I'll be honest. I love take-home coding challenges for interviews.

Yes, I'm not getting paid to write code for some company on my personal time—but I'd choose it over a "traditional" data structures / algorithms technical interview any day.

(I have no problem with pair programming interviews. I just think that live-testing candidates on Leetcode puzzles/trivia doesn't make very much sense.)

Recently I was presented with the following take-home challenge as part of one company's interview process.

The challenge: Create a color swatch picker in a public CodePen.

Requirements

  1. Build the component using only vanilla JavaScript.
  2. Two or more of these components should be able to exist on the same page.

After toying around with some not-very-good ideas on how to approach this, I decided to give Web Components a try.

Why Web Components?

Even though Web Components was introduced by Google in 2011, I only started hearing some buzz about it within the past year. Particularly with respect to Eleventy, which is said to play pretty nicely with it.

Eleventy's ability to cooperate with Web Components makes it quite powerful as a static site generator, even though it doesn't rely on any frontend JavaScript frameworks like React or Vue. While either one of those would be perfectly capable of creating a reusable and extensible color picker component, pulling in a frontend framework would not be vanilla JavaScript—and would certainly be overkill for a small project like this.

That said, I still wanted a method that was more elegant and less bug-prone than the first one that came to mind:

  1. <!-- Create two or more of these divs -->
    <div class="color-picker"></div>
    <div class="color-picker"></div>
  2. const colorPickers = document.getElementsByClassName('color-picker');

    Array.prototype.forEach.call(colorPickers, (colorPicker) => {
    /* Set innerHTML and add event listeners here */
    });

Above all, it's always cool to learn about useful functionality that's provided natively by web technologies. For example:

Implementation notes

tl;dr

What is Web Components?

Web Components is an API that allows you to define custom HTML elements. The reusability it promotes is kind of like CSS custom properties, but you can reuse (and override) HTML templates, JavaScript functionality, and styles that are specific to your component. The API consists of three technologies:

  1. Custom HTML elements, which define a web component's tag name (something like <accordion-menu>), internal properties, and behaviors
  2. Shadow DOM, used with custom elements to safely separate a web component's own DOM subtree from the containing document
  3. The <template> and <slot> HTML elements, which enable component HTML reuse and "plugging in" values into components, like a styled button's label

In case it's confusing...I refer to Web Components (the proper noun) as singular, and web components (the common noun) as plural.

What browsers support Web Components?

At the time of writing, Web Components is fully supported on Firefox and Chromium-based browsers, partially supported on Safari (mobile and desktop), and not supported on Internet Explorer.

What's a shadow root?

A ShadowRoot provides a means to access the shadow DOM that's owned by an instance of a web component. It exposes DOM functions like querySelector and appendChild.

What's attachShadow({ mode: 'open' })?

It's called on an HTMLElement, and returns a reference to its ShadowRoot.

If { mode: 'closed' } is used, null will be returned, and you won't be able to access the element's ShadowRoot from the context in which attachShadow is called.

What's cloneNode(true)?

cloneNode returns a Node that's a copy of the Node it was called on.

true is a value for deep, the one argument that can be passed to cloneNode.

deep is optional, and defaults to false. If deep === true, the node and its subtree (including Text nodes) will be cloned.

<ol id="someList">
Only two things are infinite:
<li>The universe</li>
<li>Human stupidity</li>
</ol>
let shallowClone = someList.cloneNode();
// => <ol id="someList"></ol>

let deepClone = someList.cloneNode(true);
// => <ol id="someList">Only two things...<li>...</li><li>...</li></ol>

Why are <template> and its children invisible?

<template> elements aren't rendered in the document. But they can be accessed from within JavaScript, and are useful for inserting custom elements into a document using a predictable HTML structure.

What's disconnectedCallback?

disconnectedCallback is kind of like React's componentWillUnmount or Vue's beforeDestroy. This is where you perform cleanup like removing event listeners.

It's part of a series of lifecycle callbacks that are executed at specific times in the lifecycle of a custom element.

What's :host?

Within template > style, the :host CSS selector targets the component itself. This allows you to write scoped styles, including CSS custom properties.

Conclusion

I've barely scratched the surface here. Web Components is a highly flexible set of web features that allow you to customize and extend HTML elements, which is pretty compelling. If you've got some custom functionality you want to reuse, defining an <accordion-menu> will be a lot more semantic and future-proof than div > div + div ...

While web components are still evolving, there's a lot of support for them in the open-source community—in the forms of both component authoring tools, as well as libraries of published components—like Polymer and WebComponents.org, respectively.

For a more detailed and practical look at Web Components, check out this CSS-Tricks guide that I found immediately after submitting my coding challenge. 🙃

Hopefully "Web Components" still looks like real words to you after reading it so many times.