Web Components For Your Custom Elements
Tags: webcomponents, javascript
Published: 2017-03-11 18:23:03

---
title: Web Components For Your Custom Elements
published: true
description: Using Web Components to enrich your front-end development.
cover_image: 
tags: webcomponents, javascript
---

_TL;DR Here is a [repository](https://github.com/kay-is/webcomponents-bootstrap-example) with a working example. :)_

This week the Polymer project [announced](https://www.polymer-project.org/blog/2017-03-08-2-0-rc.html) their 2.0 release candidate, which uses the new (ES2015) class based spec of custom elements v1.

That post made me think about the future of component based development on the Web in general. 

## CSS & HTML Framework Based Components

I've seen many projects created by using a CSS framework like [Bootstrap](http://getbootstrap.com/). The idea is simple, the frameworks define reusable components, which are independent from the rest of the application. This is accomplished by using HTML and CSS as an interface.

At the _top_ of your app, you include the Bootstrap CSS and at the _bottom_ of your app, you have to use the classes in your generated HTML to render a component. 

For example, a progress bar component in Bootstrap:

    // Use
    <div class="progress">
      <div class="progress-bar" style="width: 60%;"></div>
    </div>

As you can see, in consists of two `<div>`s and they need specific CSS-classes and style. To replicate the behavior you need HTML and CSS.

Now, because every JavaScript framework lets you generate HTML and CSS, you can use the progress bar independent from this framework. Create a whole app in Ember with help of HTMLBars templating language and later rewrite the whole thing in React with JSX. Different JavaScript based technologies, but they both interface with HTML and CSS.

The problem is, you still have to write the correctly nested HTML and sprinkle it with the right CSS classes.

## JavaScript Framework Based Components

Component based JavaScript frameworks like [React](https://facebook.github.io/react/) already solve that problem.

For example, the progress bar written as React component:

    // Define
    function ProgressBar(props) {
      return (
        <div className="progress">
          <div className="progress-bar" style={{width: props.complete}}></div>
        </div>
      );
    }

    // Use
    <ProgressBar complete="60%" />

Now you can use the progress bar in your app without worrying about the HTML or CSS structure. If Bootstrap changes its classes or its HTML later, you can simply go to your React component and change it there.

__But!__

It's a React specific solution and your have to maintain your own implementation.

Wouldn't it be nice, if Bootstrap simply provided you with such a component, usable in your obscure framework of choice?

__Custom Elements to the rescue!__

## Custom Elements Based Components

Web components, a set of specs for framework-less components, tries to get you out of this mess by providing a [W3C spec](http://w3c.github.io/webcomponents/spec/custom/) for creating such components. It's basically _a browser API for creating your own HTML elements_.

This adds the missing _bottom_ to CSS and HTML based frameworks like Bootstrap, which define CSS classes at the _top_ and require you to add them to your _correctly structured_ HTML in all the right places.

They could provide you with an HTML element, that specifies its whole interface via HTML attributes, like Reacts components do via props. If they want to change the implementation, they had access to the CSS at the _top_ and the HTML at the _bottom_.

For example, the progress bar written as React component:

    // Define
    class BootstrapProgress extends HTMLElement {
      connectedCallback() {
        const progressBar = document.createElement("div");
        progressBar.className = "progress-bar";
        progressBar.style = "width: " + this.getAttribute("data-complete");

        const progress = document.createElement("div");
        progress.className = "progress";
        progress.appendChild(progressBar);

        this.appendChild(progress);
      }
    }

    customElements.define("bootstrap-progress", BootstrapProgress);

    // Use
    <bootstrap-progress data-complete="20%" />

This component is based on browser internal APIs. Since it defines a regular HTML element, it can be used in all frameworks that can create DOM elements.

## Conclusion

Custom Elements are a nice way to encapsulate UI components that make up your application.

Sadly, Custom Elements aren't implemented in all major browsers yet. Firefox is still implementing and Edge hasn't even started and you can't blame them. As the Custom Element spec says:

> This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

But, thanks to the magic of [polyfills](https://github.com/webcomponents/webcomponentsjs), you can use Custom Elements even in non-conforming browsers.