đŸ€˜đŸ»A brief history of WebComponents and a tutorial to make yours

Lior CHAMLA
Apprendre le web avec Lior
8 min readAug 17, 2017

Ending 2013, I discovered AngularJS and its features : Finaly a way to extend DOM to fit a better semantic, more understandable elements, dynamic data bindings, etc.

Then, as every web developer, I got to learn React and I’m now using a lot Angular. That’s great, but hey, is there a standardized way to extend DOM without having to put all these libraries and node modules ?

In fact, there is a way : Web Components specification. Here is a brief history of this concept and spec.

First attempts : Microsoft HTML Components and Mozilla XBL

The first attempts to extend the default DOM API came from browser companies (as usual) to provide developers features that would enhance possibilities on the web.

Microsoft HTML Components (HTC)

HTML Components were created by Microsoft in 1998. The goal was to extend the DOM by creating new directives (attributes) which could change the behavior of default tags. It was relying on JScript or VBScript and Microsoft ActiveX was required.

The implementation was quite complicated and too much restrictive (working only on IE 5.5 and later).

In 2011, Microsoft abandonned this feature and it was deprecated on IE10.

Mozilla XML Binding Language (XBL)

Mozilla XBL stands for XML Binding Language and was created in 2001 followed by XBL 2 in 2007. The goal was also to extend default DOM tags with custom behavior. These extensions used to work on all Mozilla products.

In 2012, XBL2 was abandonned and is no more implemented on any browser.

The concept was good : extending the DOM with custom tags that will enhance readability and reusability. The implementations were not.

Implementing the concept with universal javascript frameworks (Angular, React, Ember, and the others)

Taking note of the differents problems that are inherents to a vendor oriented approach (Microsoft creates his own thing, and Mozilla does his own thing, etc), developers decided that they had to create cross browser compatible libraries to implement the WebComponents concept.

Google’s Angular

To fullfill the legitimate need for a better semantic on web apps and to allow developers to create their own tags, AngularJS was born on 2009, then released on GitHub in 2010. Google took a great care of this framework, until version 1.0 was available in 2013. It is now on his fourth version and relies on TypeScript and ES6 classes.

Facebook’s React

On the other hand, and also to fullfill the need of reusable widgets, Facebook decided to create it’s own library : React was born in 2011 and was released on GitHub in 2013, creating a web dev big bang. It is now used by many world class companies and every web developer has at least read some docs and tried it.

It allows you to create custom tags which are backed by a Javascript implementation which defines what the tag is supposed to do and how it will render on the browser.

There are plenty of other libraries which will help you to do the same : creating custom, scoped and reusable widgets to extend the DOM and add more declarative and descriptive tags to your webapps.

What about a standardized specification ? The W3C WebComponents !

Logo from http://webcomponents.org

On the impulse of Google and other companies, the W3C launched the WebComponents specification (you can still find the first published draft which was released in 2012) which aims to bring back the concept of custom and reusable tags in the standard. A standard that would be implemented in the same way by all the browsers in the future and it would work without any need of a vendor’s library.

It is still not completely released for now but W3C is working on it and Google is taking it very seriously, implementing as soon as possible all the changes which are made to the spec.

How does it work for now ?

I say “for now”, because the spec and implementations change very often ! This is still an “experimental” spec and it evolves quite quickly.

It relies on 4 concepts :

  • Custom Elements : this provides the way for a developer to create a custom tag and specify how it works, what attribute he can have, how it reacts to differents events and how it has to be render
  • Shadow DOM : this provides the possibility of encapsulated and scoped DOM tree, including CSS
  • HTML Template Tag : this provides the possibility of declaring tags which will be parsed by the browser but not interpretated. The code within a <template> tag won’t be displayed until you activate it by cloning the template tag content
  • HTML Import : this provides the possibility of import external HTML file into your HTML file. This is the default way to create components files (like my-widget.html) which will contain a component, and to import it in your master document (like index.html)

Let’s write our own HTML tag !

As I said earlier, the WebComponents pattern relies on 4 pillars : Custom Elements, Shadow DOM, Template Tag and HTML Import. Let’s implement each of them progressively

Creating a Custom Element

We want to create a custom HTML Tag named <employee-presentation>. This tag will present us an employee of our company, with his picture (taken from avatars.io), his name and position in the company.

Here is the actual implementation (you can edit it in JSFiddle) :

Look the Result tab to see that it works ! Without any fancy framework (e.g. Angular or React)

So here, we created a custom <employee-presentation> tag which can take several attributes :

  • full-name: represents the full name of the employee (here: Lior Chamla)
  • job-position: represents the position of the employee in the company
  • avatar-service: represents the social network from which we will take the avatar (here: twitter)
  • avatar-user: represents the user which holds the avatar of the employee on the social app we specified in the avatar-service attribute (here: LiiorC)

In order to understand what he has to do with the <employee-presentation> tag, the browser has to look at the JS class EmployeePresentationElement. This class will manage attributes data and will render the component !

Limitations of this system for now :

  • You have to specify the rendering with a call to .innerHTML by passing it a template literals string
  • The CSS styles we defined for our component “bleeds” on the outside so it messes up our page’s styles

Avoiding CSS “bleeding” with the Shadow DOM

We first want to set things right with our components CSS which for now can go outside of our component and interact with our master page elements ! This is a problem. Can we encapsulate for real our component styling and behaviors ?

Yes ! With the Shadow DOM. The Shadow DOM is like a hidden part of the DOM which is really scoped ! It will be interpretated by the browser but will be considered as a closed tree in our global page.

If you look the Result tab, you will see that our CSS has no more effect on tags which are outside of the component ! Yihaa !

Yiihaa ! We no longer have this CSS leaking problem ! The CSS which is declared inside the Shadow DOM is scoped to this area and does not bleed on elements which are outside of our component ! This is a great news !

The only difference between this component and the first one is that here :

  • We create a Shadow DOM which will be attached to our custom tag
  • We render the string inside the Shadow DOM instead of rendering it directly inside our custom tag
  • All of our code is now scoped inside the Shadow DOM, and you can see the H3 outside of the component is no longer affected by the CSS which was declared in our component !

Limitations of this system for now :

  • You have to specify the rendering with a call to .innerHTML by passing it a template literals string

Using HTML Template tag to hold our template

So the W3C issued a new <template> tag which can hold HTML markup that will be read by the browser but wont be interpretated or rendered. So you can have entire component’s templates written in your page without end user even noticing it. This take no additionnal time for the browser to load the page because it wont try to interprate or render the inner markup of the template tag !

Even if ES6 template strings are great, we could nest our rendering code inside a template tag and then just clone the content of the template, modify it with our datas, and then rendering it inside of our Shadow DOM !

Look at the HTML tab to see our new <template> tag and then look at the JS tab to see what changes were made !

Great ! We ne longer hold our rendering markup in a Javascript string and we no longer use it as a .innerHTML value. We are now fully using the DOM API.

The whole rendering markup is added to our Shadow DOM and our custom tag successfully displays on the page !

The HTML Imports

Now we have a new issue : how can we encapsulate the whole <employee-presentation> logic and rendering in one and only file, and then use this file in all the pages which need our custom tag ?

Easy, with HTML Imports, W3C made it really simple : <link rel=”import” href=”employee-presentation-component.html”/>

I can’t show you this right now, because JSFiddle does not allow me to edit a multi files project, but you got the point !

Conclusion : can we use WebComponents ?

So, this is a long way to the top if we (web developers) want to reach a standardized way to implement the WebComponents concept ! As everything which is hold by the W3C, it takes years and years to grow and to be mature enough to get implemented in all our browsers.

For now, only Google Chrome is committed to this approach and implements ASAP new features released by W3C. Mozilla said it wont implement these concepts for now and to be fair, no one is really taking interest to the WebComponents approach except Google.

Compatibility table for WebComponents on CanIUse

But, and it is a big but : there are polyfills ! You can find polyfills all over GitHub to enable this logic on any browser !

So, should we use WebComponents ? My answer would be : even if there are polyfills, even if it could work on every browsers, this is still a work in progress spec. It changes each year, even every month for several APIs.

So just use it to know what it feels like to create Web Components without any library to help you on it, use it also to encourage W3C and all this ecosystem to move quicker on this spec, but dont take it to a production level (at least not without a library like Polymer or other stuff like that to ensure it will work as you want it to work on all browsers and for all time).

Sources and resources

--

--

Lior CHAMLA
Apprendre le web avec Lior

DĂ©veloppeur web full stack et formateur pour plusieurs groupes de formations et Ă©coles (CESI Alternances, eXia, 3WAcademy et WebForce3)