An Introduction to Web Components

08 November, 2015
post-banner

“There’s an <element> for that” - Google I/O.

Web components have been a controversial issue in the development world in the last couple years and many people are still debating their role in the future of the web.

In this article we're going to look into the evolving world of web components and how they will create a useful impact on the development of the web. We'll also have a look at the Polymer project, developed by Google, to use some web components in a real project. Then we can start to look into how we can create custom web components that can be reused inside of our projects.

What are Web Components?

Web components are a new collection of web standards which are currently heavily in development and working their way through the W3C. They basically allow developers to bundle markup and styles into reusable, custom HTML elements which can then be called anywhere within a project. Web components fully encapsulate HTML and CSS, this means the styling always renders as you would expect and the component is safe from any external JavaScript.

The main idea is that you should be able to name an element after what it does, assuming it always performs the same role, with the same properties and functions applied.

Currently, Chrome and Opera are the only browsers with full support, but Firefox is in development. There is a Mozilla alternative to Google's Polymer Project called X-Tags.

Web components are made up of four different web specifications: custom elements, HTML templates, the shadow DOM and HTML imports. These four features allow developers to create simple, reusable and interoperable HTML elements with completely isolated styles and custom behaviour.

Custom elements

Custom elements extend the web as they allow you to create and define completely new element tags that can be used inside of your markup code.

When creating a new web component, you are able to give it a custom element name. They can be brand new tags entirely, or extensions of existing elements with additions UI or functionality. This is great and will allow you to write markup code which is more semantic and understandable.

The custom elements must be name-spaced with a hyphen. This is because the specification reserves single word names for future elements to be developed with no interference.

HTML templates

HTML templates define a template in chunks of markup which are inert until you instantiate them on the web page. This is similar to using another browser-side templating language such as Mustache.js or Handlebars.js.

Shadow DOM

The shadow DOM encapsulates CSS to your custom element. It makes the element styles independent to the main document, which can be very useful. This is one of the more problematic and debated aspects of web components, but also one of the most useful. This is already used by some browsers for image sliders and video elements.

HTML imports

HTML imports extend the link element which is used to import stylesheets, by importing the web components stored in an HTML element by using similar syntax.

<link rel="import" href="my-element/my-element.html">  

Why all the fuss?

Using web components keeps your code clean and DRY. If you look at the source code of many large web applications it is usually a mess of divs and too many tags to be able to follow easily. Take Gmail as a great example.

gmail-source

As you can see, Gmail’s source code is a div-soup mess with shortened class names that don't really make sense to anyone reading them externally. With web components the code is much cleaner and will make sense to most developers who happen upon them.

Components are reusable across an application, and this can make the development process faster and much more efficient. There is a large catalog already available so developers can concentrate more on application/task specific components to be able to build larger applications without having to reinvent the wheel every-time.

Interoperability is another thing to consider. For example, you may want to use the styles for a button from the Bootstrap framework, when you are already using the Foundation framework for your application. Using a mix of CSS frameworks can be risky as it is hard to tell how the styles and scripts from each will interact with each other. This is less likely a problem with web components because the shadow DOM hides the components CSS from the host page.

Some debated problems with web components

As with every new web standard, there are several controversial debates regarding the potential problems of the specification.

Semantic code is an issue for some developers and there are a lot of arguments as to whther tags like <img-slider> are actually better than the current method of using a vast amount of divs.

Some developers are strongly against the use of <style> tags written inside of markup. Because link tags don’t work inside of the shadow DOM, using style tags inside of the components template is unavoidable.

In my opinion, the main problem currently is the lack of browser support, but with the use of Polyfills this is less of a problem.

Web components are a new web technology so this is always a problem in the early stages. Most browsers are working hard to fully support them and are considered to be an important aspect of future web development.

Polymer

So, what exactly is Polymer?

The Polymer library is designed to make it easier and faster for developers to create great, reusable components for the modern web.

Polymer isn't web components, and it's not elements either. It is built on top of web components to help developers create their own elements easily, and provide an extensive library of custom elements. Polymer provides a 'declarative syntax' to help you build powerful elements that are DRY.

Polymer also isn’t a framework. You are able to use Polymer components inside of your Ember/Angular/React/*MVC application and they will work as you would expect them to.

Here is a great playlist of keynotes from the first ever Polymer summit in Amsterdam.

Another great resource for finding elements is CustomElements.io where developers can share their own elements.

Polymer provide a great ‘starter kit’ which allows developers to quickly jump into a Polymer project with a large amount pre-installed components ready to be used.

The Polymer starter kit comes with a whole bunch of useful features, such as:

  • Material design
  • Unit testing
  • Live browser reloading
  • Build tools
  • Custom themes
  • Responsive boilerplate

The Polymer Element Catalog

If you don't want to write your own elements, Polymer provides quite a broad library of elements available to developers. These elements are categorised into seven different types of element:

polymer-catalog

  • Iron - Includes elements for working with layout, user input, selection, and scaffolding apps.
  • Paper - Paper elements are a set of visual elements that implement Google's Material Design.
  • Google Web - Components for Google's APIs and other services.
  • Gold - The gold elements are built for e-commerce use-cases like checkout flows.
  • Neon - Implement animations and special effects.
  • Platinum - Elements to turn your web page into a true web app, with push, offline, bluetooth and more.
  • and, Molecules - Molecules are elements that wrap other javascript libraries. Currently there is only an element to write markdown inside of HTML, but there are more being developed.

Setting up a Polymer project

Yeoman have a great package for generating a new Polymer ‘starter’ project, with build support for Gulp. This package contains a large amount of Iron and Paper elements that you may not need to use, but is probably the best way to get stuck in and learn how to use Polymer elements and web components in general.

To set up a new Polymer project using the Yeoman generator there are a couple of important prerequisites. Open up your terminal and enter the following commands to get started:

$ npm install -g yo
$ npm install -g generator-polymer

This will globally install Yeoman and the Polymer generator package. Next you can create a new directory for your project, cd into it and call yo polymer to scaffold the project. This will automatically bower install && npm install the necessary packages for you, so there is no need to do this yourself.

$ mkdir polymer-project && cd polymer-project
$ yo polymer

Because this package comes with Gulp support, all you need to do to run the project is call the serve command.

$ gulp serve

The browser should open the project at localhost:5000 and you will be displayed with the starter pack home page.

polymer-starter-kit

Any changes you make to the project will automatically reload and be displayed in the browser as the gulpfile contains browser reload functionality.

If you look through the source code for the project in your editor you can browse through the pre-installed elements inside the bower_components directory. It is a good idea to look at the source for them and it will help you to understand how the elements work.

If you open up the app/index.html file you will see loads of Polymer elements being used to make up the structure of the page.

Adding elements from the catalog

Not all of the elements from the catalog come pre-installed with the starter pack, in fact just the Iron and Paper elements are included. If you search through the catalog and find something you would like to add to the project, you are able to install and use the component easily.

For this article we will install and use the google-map with google-map-marker elements from the Google Web Components section.

First off, in a new terminal window, let's install the elements by running the following.

$ bower install --save GoogleWebComponents/google-map

Next go to the app/elements/elements.html file and import the new elements beneath the pre-installed ones.

<link rel="import" href="../bower_components/google-map/google-map.html">  
<link rel="import" href="../bower_components/google-map/google-map-marker.html">  

You will notice that there are two different types of import for the google-map component. This is because you are able to add extra elements as options for the component. The google-map-marker element will allow us to add a marker to the location we select inside of the Google map.

Let’s open up the app/index.html file and add the elements to the page.

<paper-material>  
    <style>
        google-map {height: 500px;width: 800px;}
    </style>

    <google-map latitude="37.77493" longitude="-122.41942" fit-to-markers>
        <google-map-marker latitude="37.779" longitude="-122.3892"></google-map-marker>
    </google-map>
</paper-material>

This will render a Google map on the page at the exact position set in the latitude and longitude (SF). If you have imported the correct elements to the elements.html file it will also render a marker at the position set. You will need to set the width and height styles for this element to properly load. The &lt;paper-material> is used to add the component on a ‘card’.

map-example

Now you can see that the Google Map have successfully rendered on the page. You can repeat the previous steps with any of the Polymer elements in the catalog, so check out the element catalog.

Creating a custom element

Creating and adding custom elements to your Polymer project is really simple. For this article we are going to create a &lt;user-avatar> component using the avatars.io service. This component will take in the desired social service, and the username of the user.

To add the custom element to the Polymer project you can simply run:

$ yo polymer:el user-avatar

You are then asked whether you would like to import the element into the elements directory, and whether you would like to create a test for the element using the TDD or BDD type. It’s a good idea to select ‘Yes’ for both options.

├── elements
│   ├── elements.html
│   ├── user-avatar
│   │   └── user-avatar.html
│   ├── my-greeting
│   │   └── my-greeting.html
│   ├── my-list
│   │   └── my-list.html
│   └── routing.html

As you can see, the new element is then added to the elements folder, and should have already imported it into the elements.html file for you.

A basic element will be created which will import Polymer into the file, a DOM id will be set to the name of the element, and a basic template and some shadow DOM styling will be configured.

To add the functionality for the user-avatar component couldn’t be simpler. All we add is an image source to the ‘avatars.io’ link with a template helper for the service and username. We can also set some styles to configure the size of the avatar.

<link rel="import" href="../../bower_components/polymer/polymer.html">

<dom-module id="user-avatar">  
  <template>
    <img src="http://avatars.io/{{service}}/{{username}}" />
    <style>
     img {
       height: 60px;
       width: 60px;
     }
    </style>
  </template>
  <script>
  (function() {
    'use strict';

    Polymer({
      is: 'user-avatar',

      properties: {
        foo: {
          type: String,
          value: 'user-avatar',
          notify: true
        }
      }
    });
  })();
  </script>
</dom-module>  

Now, with this code we will be able to call the user-avatar element inside the project, define a service (Twitter/Instagram/Gravatar) and set the username for the user.

<paper-material>  
    <user-avatar service="twitter" username="danielgynn"></user-avatar>
    <user-avatar service="instagram" username="danielgynn"></user-avatar>
    <user-avatar service="gravatar" username="[email protected]"></user-avatar>
</paper-material>  

This will render three identical avatars to the page inside of a card because I have set Twitter, Instagram and Gravatar to use my usernames to retrieve the image.

avatar-demo

This simple, custom web component was really easy to create and utislise inside of a project. Powerful components with much more functioanlity are able to be created in exactly the same way to fully take advantage of the reusability of web components.

A Bet on Web Components

There is a great deal of support for the development of web components and many frameworks are taking great leaps to implementing them. Ember.js is pushing for its developers to be using reusable components for their applications, rather than the standardized controllers. I feel there is a long way to go until web components are a ‘normal’ way of developing web applications, but it’s safe to say they are going to be a big part of the future of the web.

Further Reading

comments powered by Disqus