Introduction to Custom [HTML] Elements (CSS ART)
Tags: javascript, html, codepen, css
Published: 2020-12-13 17:56:58

# What are Custom [HTML] Elements?
Custom Elements are reusable html elements which can encapsulate implementation details into components. Custom Elements are part of the Web Component spec, which is supported by all the major browsers. Custom Elements can be used to bring the component model of React/Angular/Vue to the native web platform without any added dependencies costing valuable network capacity.

# What do Custom Elements look like?
Here's an example:
{% codepen https://codepen.io/barakplasma/pen/JjREOvx default-tab=result %}

For this example, and in honor of the current Jewish Holiday of Hanukkah, I decided to create a Custom Element for Menorah lights. A menorah has 9 spaces for lights (candles or oil lamps) in total. Each night of Hanukkah, we ignite one more light using the helper light, the shamash. The shamash is always a bit taller than the rest. 

Let's take a look at the HTML to see what makes this special:
{% codepen https://codepen.io/barakplasma/pen/JjREOvx default-tab=html %}

Rather than rewrite the same HTML 9 times (span>img.candle), I created one reusable custom element for a candle. A "candle-el" can be (lit or unlit) and (normal or shamash). We can create custom attributes on custom elements which can modify that element's styling, behavior, or contents. In this case, each candle listens for the "lit" and the "shamash" attributes to see if it needs to have different styling. I want this to work like the "checked" attribute on HTMLInputElements.

(Homework idea: Click "edit on codepen" and try adding and removing "lit" from the various candle elements in the codepen to see how it changes the styling.)

# How do I get started with Custom Elements?
Custom Elements are probably built into your browser, and require no transpilation/bundling/etc, so all you'll need is your browser and a text editor. Codepen is great for this.

Since the appeal of Custom Elements is no dependencies, let's try getting started without any frameworks. While Custom Elements are a useful tool even in a React/Angular/Vue project, we don't need those to get started.

To begin with, we'll need some experience with Javascript. Web Components are built by defining Custom Elements in Javascript. Let's take a look at the Javascript from the example.
{% codepen https://codepen.io/barakplasma/pen/JjREOvx default-tab=js%}
The line at the bottom of the Javascript file defines the Custom Element for use in our HTML.
```js
customElements.define(
  /*custom element name=*/"candle-el", 
  /*Javascript class for the custom element=*/Candle
);
```
The Javascript class must extend an HTMLElement. Within the constructor, we need to call super() and create a shadow DOM root. Later on in the constructor, we need to append the elements within the Custom Element to that shadow DOM root. The shadow DOM root is how we encapsulate the HTML and CSS for the custom element. That shadow root isolates the component from its siblings and parents. You can see this if you inspect element on any candle.

Custom Elements are mostly created with Javascript within the constructor. As you can see, I used `document.createElement` `Element.appendChild` and `Element.[has/set/get]Attribute` through out the constructor to create the elements. This is vanilla Javascript, available without Custom Elements as well. As an aside, React also uses `document.createElement` to create elements for rendering into the DOM.

# Conclusion
Web Components are a standardized and future proof tool for Frontend Web Developers to build consistent experiences. With just a bit of vanilla (ordinary) Javascript, HTML, and CSS, we can create well encapsulated, reusable, and fast loading Custom Elements which can be used across projects and frameworks.

## More resources
* [MDN: Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components)
* [MDN: Using Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)
* [Google: Custom Elements tutorial](https://developers.google.com/web/fundamentals/web-components/customelements)
* Just in case CodePen doesn't work for you, here's the same thing as a [Github Gist](https://gist.github.com/barakplasma/b78bc7c9dc1d6a7182a3a52d3d17315a)