Introduction to Custom Elements
In yesterday’s post I made the case for Web Components so today let’s dive back in and look at Custom Elements.
So, what are Custom Elements?
The W3C Introduction to Web Components defines Custom Elements as follows:
custom elements let authors define their own elements, including new presentation and API, that can be used in HTML documents
To translate that a little bit, consider that every HTML tag inherits from HTMLElement. Often in the W3C specs they’ll shorthand that and refer to items in the DOM as just “element” or “elements”. So what this is basically saying is that the custom elements spec lets you define new HTMLElements, which is kind of like saying you get to define new HTML tags. Technically it has always been possible to create your own HTML tags by shimming the browser, this is in fact how HTML5shim makes legacy browsers recognize HTML5 tags, but these tags weren’t really first class citizens. Which is to say, they could work as containers but if they needed to do anything else like spit out some custom DOM (think the
<video> tag or an
Custom elements solves these issues by letting you define new markup which can then have a whole lifecycle of events, unique styles that are only scope to the element and additional (hidden) HTML markup.
Defining a new Custom Element
It’s probably easier to grok all of this if you just see some example code. Let’s look at the proposed markup for defining a new custom element.
The W3C definition of this is painfully muddled:
“The element element defines a custom element. It specifies the type of element it’s a refinement of using the extends attribute.”
To translate, you create an element tag, give it a unique identifier with
name and specify which tag you’re extending. All custom elements must extend an existing tag and ideally it should be a tag that they closely relate to. In this case we’re creating a new custom element called
x-dropdown-button which extends
<button>. The docs suggest that if you don’t have a closely related tag that you should just extend
<span> since (at a minimum) you know that your element is related to a container of some sort. As a fallback legacy browsers will then use the original tag and at least render something that is close to your intent. Maybe IE8 won’t get a
x-dropdown-button but at least it’ll get a
Defining Custom Elements with Templates
If you recall I said that Custom Elements can define additional markup, similar to the
<video> tag or an
<input> field. This markup is specified through the use of a
<template> tag. For example:
If a custom element includes a template then it will be cloned into that element’s shadow DOM when the browser parses the tag. We haven’t talked much about shadow DOM yet but for now just think of it as markup that’s rendered on the page but not inspectable by the client.
Any content that would normally live inside of the extended tag ends up inside of the
<content> tag in the template. For instance if we extended
<button>Hello World</button> then “Hello World” would end up in the
In addition to markup the template can include styles that are scoped only to the custom element. Here’s the same example from above with the addition of a scoped style tag.
The CSS used in the scoped style tag will not affect anything else on the page so you can have your own
.dropdown-menu classes and they won’t conflict with the component. The component author can expose style hooks for the consumer to alter the appearance of the element through the use of the new
elsewhere in a style.css you could say:
Using Custom Elements in Markup
Using a custom element is really straightforward thanks to the new
is attribute. To use our new dropdown-button from above would just be:
You can also create custom element in script like so:
Also you can specify a
constructor attribute and then use it to create new instances of your element.
Additionally you can add methods and properties to this constructor and call them later:
Constructors are attached to the
window object, but if you don’t want to pollute that scope you can use the
Unfortunately, at least to my knowledge, custom elements are not currently supported in any major browsers. However Chrome has added support for 2 of the 4 Web Components standards in their last two releases so I can’t help but think that custom elements are right around the corner. One thing I didn’t touch on very much in this post was shadow DOM which currently is supported in Chrome so tomorrow I’ll talk about that technology. Till then!
You should follow me on Twitter here.