Don't like this style? Click here to change it! blue.css

Class 18: Web Components

This is a concept which has a very strong chance of altering the future of web development. At first I didn't understand why it was any different than the current methods. Here is the promise of web components:

You can create or choose from a pool of custom tags that make whatever widget you need.

There are 4 technologies that coalesce into web components:

Imagine grabbing whatever component you want from whomever you want. For instance the next tag in this document is simply <google-map latitude="39.679702" longitude="-75.751483" map-type="satellite" zoom="18" ></google-map>

Building Web Components

Because the above features are not widely supported yet (and may never be), we use what's called a polyfill. That is, a library that covers missing functionality (but checks for support first). In this case that means adding the library to your HTML.

Here is a working vanilla web component: (I'm using Plunker for this one because I wanted multiple files.)

Custom Elements

The secret sauce for custom elements is this:

      document.registerElement('ninja-killa', {
          prototype: $baseElement

That line tells the DOM that tags with name ninja-killa should use $baseElement as their prototype ($baseElement was just a variable name of mine). It was decided that custom tags MUST CONTAIN A DASH to avoid conflict with normal tags.

See the Pen Custom Components by Andy Novocin (@AndyNovo) on CodePen.

Build a Tag Create a counter tag which has a method start. When start is called the counter should begin counting upward from 1 once per second. Display the current count value in the innerHTML. Put 5 counter tags on your page and add an event listener to each so that a click triggers start.

Lifecycle Callbacks

This totally optional feature lets you have your custom element react to interesting moments in time. The four moments you can react to are:

Better Counter Now update your counter so that it has two attributes is-running and count. When the element is created register the click listener which toggles the is-running attribute. Have an attributeChangedCallback which starts or stops the timer when is-running is toggled from true to false, and updates the innerHTML when the count is changed. Now create a tag which is already running and starts at count 20 to your page by using <counter is-running="true" count="20"/>.

Shadow DOM

This concept allows you to create new webpages/DOMs inside of your document that live in their own world. For instance, imagine that you had a CSS rule on your main page for all divs. Now you want to use someone else's gmail widget and it is loaded with divs. Your CSS would be applied to their widget. A Shadow DOM is its own kingdom, with CSS, HTML, and Javascript all its own.

The secret sauce of shadow DOM is to take an element and do something like:

        var shadow = $someElement.createShadowRoot();

Now anything you add to shadow is in a bubble. For instance, look at my ninja-killa example. Those SHADOW doms have the CSS rule * {color: salmon} and the normal paragraph is unaffected. Likewise .ninja { color: orange} in the main document would have no impact on the ninjas.

See the Pen Custom Components by Andy Novocin (@AndyNovo) on CodePen.

Shadow Play create a shadow root on an element. Give that shadow DOM a totally different style than the dom as a whole. Make some listeners at both levels and convince yourself that you understand it all.


It's already clear that I hadn't used the template tag before (it was missing from my notes on templates). The missing part of the formula is that the template tag comes with a content attribute for cloning. It is typically used with another cloning command document.importNode($template.content, true) (the true is for a deep copy).

HTML Imports

This feature, like the ES6 module loading, is up in the air while specs shake out. Firefox won't support it until the ES6 module loader is up and running. So for now polyfills will be needed. You'll pretty much only see this feature in the context of web components as of 2016.

The goal is to have a single file component that you can share around with your friends. For instance the ninja component was made like this:

The secret sauce of HTML imports was

      <link rel="import" href="other_component.html">

It was also a little bothersome to find a way to grab the template purely from the second file, which was this: document.currentScript.ownerDocument

Build a world

OK, build several animal components (I recommend plunker today because of the multi-file aspect). Build a nice looking animal using however many divs you want, but hide it in the shadow DOM of a simple tag. Populate a page of animals. Can you have them wander around?