Web Components


Custom Elements

There are many different kinds of objects displayed on web pages: maps, documents, videos, like/share buttons, etc. While there are a few function-specific HTML elements, such as form inputs, <audio> and <video>, the rendering of those objects is controlled by - and built into - the browser. To embed other kinds of objects, or to control the rendering of a particular type of element, a generic HTML element (<button>, <span>, <div>) is used (usually with a more specific classname).

For example, to add a map to a page, you might use this:

As well as adding the <div class="map"> element, you have to import the CSS stylesheet to control the display of the map, the Javascript for it to actually render and be interactive, and also write the script that creates the new map.

It's possible to make that more generic, like this:

But then, rather than using <div class="map"> and having the parent page turn those into "map" elements, why not use an actual <map> element, and allow the display and interactivity of that element to be defined elsewhere?

Web Components

This is the point where the Web Components specification becomes relevant. It's described best in the documentation for Polymer, which provides cross-browser implementations of each part of the Web Components spec, allowing them to be used today.

The most important parts of Web Components, in this context, are:

  • Custom Elements, which lets you create new HTML elements, e.g. replacing <div class="map"></div> with <custom-map></custom-map>.
  • HTML Imports, which allows the definition (template, rendering, interaction) of those custom elements to be defined elsewhere, and imported into the current page using <link rel="import">.

Web Components also includes:

  • HTML Templates, which defines a <template> element that can be used for generating the content of new elements.
  • Shadow DOM, which allows styles and scripts defined within the custom element to be encapsulated independently of the parent page.

The map example now becomes as simple as this:

With the custom element defined in a separate, re-usable file:

Here's a live example.