ES6 Web Components Part 2 - The Building Blocks

This post is the second of five. Click here to read the first which covers why I came to Web Components in the first place.

Let's dig in. In part one, I covered WHY I wanted to write ES6 Web Components, but didn't show any code. Let's change this! Since Web Components are a collection of several seemingly unrelated techniques, bear with me as I cover one at a time and then we'll combine them all.

Custom HTML Tags #

You're most likely familiar with tons of tags/elements in HTML. You can make a div, a span, an h1, a strong tag, but did you know you make up your own tag?

To make sure I'm not steering you all wrong in my explanations, I went over to HTML5Rocks to get more basic details than I need. I did learn some cool things like the fact that if you create your own tag without a dash in the name, it inherits from HTMLUnknownElement. There's lots of cool facts to drill deeper on there if you want to be a custom tag nerd, but for our purposes, lets just talk about what we need to get up and running.

Every custom element you make needs to have at least one dash in it. I like this limitation, because it's an opportunity to namespace our work. My name is Ben, so if I had a set of elements I was making, I might call a button: . This is great to immediately know where these elements came from when you scan the code. If I made a terrible button, you might not trust the other "bens-" elements on the page.

To make my button, I can just do something like this:


document.registerElement('bens-button');

That's great (and valid), but Ben's Button doesn't do anything that a DIV tag doesn't do. It extends from something called "HTMLElement", which is just a generic sort of tag.

You can pass in a second parameter here as well. Maybe you don't want it to extend from "HTMLElement", but the "HTMLButtonElement" to make it act more like a button.


document.registerElement('bens-button', HTMLButtonElement);

You could even use JS to clone a base element like this, and make it act very custom. That's our ultimate plan, but I'm going to do this with ES6, so lets wait a bit before we dig in.

Before moving on, I should warn you that this is not a Web Standard. It is only officially supported in Chrome and Opera. You can enable it in Firefox with a configuration flag. Luckily, WebComponents.js offers a polyfill for it.

HTML Imports #

Strictly speaking, and depending how far you want to go with Web Components, HTML Imports are fairly optional. Maybe I just need simple markup in my custom element and I'm happy to create it all in Javascript. Maybe I don't care to use CSS either and I can just tweak all my style properties with JS as well.

For more complex custom components OR for the simple purpose of keeping things readable by JS, CSS, and HTML devs alike, I like to use HTML imports. These imports can suck in an HTML file onto your page. The HTML file can include Javascript and CSS to make your component whole.

So for example, in your application you can do this to include the component:


<link rel="import" href="bens-button.html">

Of course that's not the whole picture. What's in that HTML file?

Well, it could be as simple as just a script reference for Javascript that extends the HTMLButtonElement and does fancy things to it:


<script src="src/bens-button.js"></script>

To go all the way though, we can include HTML and CSS:

<script src="bens-button.js"></script>
<template>
    <span>A Button</span><button>Click Me</button>
    <style>
       :host button {
           width: 100px;
           height: 100px;
       }
    </style>
</template>

Before I break this down, allow me to first say that there are tons of different ways to go about this. What I'm presenting here is a way that I found works great for me. The bad thing about going without a framework is that you have to invent the best way to solve things. Since I'm giving you ONE way to solve things, hopefully this takes most of the badness out of a no framework solution and allows you to explore the GOOD part about not using a framework: You have complete control to tweak my ways and inject your own creative problem solving!

So the first thing we're doing is simply embedding a script tag. This script tag would contain some script to register a new DOM element and customize the hell out of it so that it truly is "bens-button".

In the next line, we have a