Web Components Demystified | CSS-Tricks - The Legend of Hanuman

Web Components Demystified | CSS-Tricks


Scott Jehl released a course called Web Components Demystified. I love that name because it says what the course is about right on the tin: you’re going to learn about web components and clear up any confusion you may already have about them.

And there’s plenty of confusion to go around! “Components” is already a loaded term that’s come to mean everything from a piece of UI, like a search component, to an element you can drop in and reuse anywhere, such as a React component. The web is chock-full of components, tell you what.

But what we’re talking about here is a set of standards where HTML, CSS, and JavaScript rally together so that we can create custom elements that behave exactly how we want them to. It’s how we can make an element called and the browser knows what to do with it.

This is my full set of notes from Scott’s course. I wouldn’t say they’re complete or even a direct one-to-one replacement for watching the course. You’ll still want to do that on your own, and I encourage you to because Scott is an excellent teacher who makes all of this stuff extremely accessible, even to noobs like me.

Table of Contents

Chapter 1: What Web Components Are… and Aren’t

Web components are not built-in elements, even though that’s what they might look like at first glance. Rather, they are a set of technologies that allow us to instruct what the element is and how it behaves. Think of it the same way that “responsive web design” is not a thing but rather a set of strategies for adapting design to different web contexts. So, just as responsive web design is a set of ingredients — including media fluid grids, flexible images, and media queries — web components are a concoction involving:

Custom elements

These are HTML elements that are not built into the browser. We make them up. They include a letter and a dash.


  Hey, I'm Fancy

We’ll go over these in greater detail in the next module.

HTML templates

Templates are bits of reusable markup that generate more markup. We can hide something until we make use of it.

Much more on this in the third module.

Shadow DOM

The DOM is queryable.

document.querySelector("h1");
// 

The Shadow DOM is a fragment of the DOM where markup, scripts, and styles are encapsulated from other DOM elements. We’ll cover this in the fourth module, including how to content.

There used to be a fourth “ingredient” called HTML Imports, but those have been nixed.

In short, web components might be called “components” but they aren’t really components more than technologies. In React, components sort of work like partials. It defines a snippet of HTML that you drop into your code and it outputs in the DOM. Web Components are built off of HTML Elements. They are not replaced when rendered the way they are in JavaScript component frameworks. Web components are quite literally HTML elements and have to obey HTML rules. For example:





We’re generating meaningful HTML up-front rather than rendering it in the browser through the client after the fact. Provide the markup and enhance it! Web components have been around a while now, even if it seems we’re only starting to talk about them now.

Chapter 2: Custom Elements

First off, custom elements are not built-in HTML elements. We instruct what they are and how they behave. They are named with a dash and at must contain least one letter. All of the following are valid names for custom elements:

Just remember that there are some reserved names for MathML and SVG elements, like . Also, they cannot be void elements, e.g. , meaning they have to have a correspoonding closing tag.

Since custom elements are not built-in elements, they are undefined by default — and being undefined can be a useful thing! That means we can use them as containers with default properties. For example, they are display: inline by default and inherit the current font-family, which can be useful to pass down to the contents. We can also use them as styling hooks since they can be selected in CSS. Or maybe they can be used for accessibility hints. The bottom line is that they do not require JavaScript in order to make them immediately useful.

Working with JavaScript. If there is one  on the page, we can query it and set a click handler on it with an event listener. But if we were to insert more instances on the page later, we would need to query it when it’s appended and re-run the function since it is not part of the original document rendering.

Defining a custom element

This defines and registers the custom element. It teaches the browser that this is an instance of the Custom Elements API and extends the same class that makes other HTML elements valid HTML elements:

My Element

Check out the methods we get immediate access to:

Showing the prototype methods and properties of a custom element in DevTools, including define, get, getName, upgrade, and whenDefined.

Breaking down the syntax

customElements
  .define(
    "my-element",
    class extends HTMLElement {}
  );
	
// Functionally the same as:
class MyElement extends HTMLElement {}
customElements.define("my-element", MyElement);
export default myElement

// ...which makes it importable by other elements:
import MyElement from './MyElement.js';
const myElement = new MyElement();
document.body.appendChild(myElement);

// 
//   
// 

// Or simply pull it into a page
// Don't need to `export default` but it doesn't hurt to leave it
// My Element
// 

A few more custom element methods:

customElements.get('my-element');
// returns MyElement Class

customElements.getName(MyElement);
// returns 'my-element'

customElements.whenDefined("my-element");
// waits for custom element to be defined

const el = document.createElement("spider-man");
class SpiderMan extends HTMLElement {
  constructor() {
    super();
    console.log("constructor!!");
  }
}
customElements.define("spider-man", SpiderMan);

customElements.upgrade(el);
// returns "constructor!!"

Custom methods and events:



Bring your own base class, in the same way web components frameworks like Lit do:

class BaseElement extends HTMLElement {
  $ = this.querySelector;
}
// extend the base, use its helper
class myElement extends BaseElement {
  firstLi = this.$("li");
}

Practice prompt

Create a custom HTML element called  that displays the text “Hi, World!” when added to the page:

Enhance the element to accept a name attribute, displaying "Hi, [Name]!" instead:

Chapter 3: HTML Templates

The