HTML & CSS
Article

An Introduction to Web Components and Polymer (Tutorial)

By Pankaj Parashar

Modern web applications are not only complex to design but also quite difficult to develop. Given the range of tools involved, amount of testing required, and the combination of libraries/frameworks used, the development process has become harder. As the application scales over a period of time, it becomes harder to maintain the code and make enhancements.

For instance, take a look at the frontend code of these few popular websites:

Frontend code of Gmail, Facebook and Amazon

Developer tools may not necessarily indicate the complexity of the actual source code, but this surely gives you an insight into the complex DOM structure of modern web applications. This is largely due to the indiscriminate usage of div(s) and span(s) in your markup that results into an unmanageable code. Much has been discussed about the semantic value of HTML5 tags but they still fall short of providing a meaningful markup, mainly because of two reasons:

  1. We have too many similar components in our web page that fall under the same semantic structure. To distinguish them from each other, we use classes, IDs, or other attributes.
  2. The available list of semantic tags are simply not enough to target the wide variety of components that constitute our design. As a result, we fall back to traditional tags like div or span.

The Solution to Semantic Madness

The W3C aims to address this problem by introducing Web Components. Web components are a collection of specifications that enable developers to create their web applications as a set of reusable components. Web Components provide a paradigm shift from the traditional approach of web design by fundamentally changing the way we build and conceive web apps.

Each component lives in its self-defined encapsulated unit with corresponding style and behavior logic. These components can not only be shared across a single web application but can also be distributed on the web for use by others.

Web components are made up of four different specifications:

  1. Custom Elements – These enable developers to create their own elements that are relevant to their design as part of the DOM structure with the ability to style/script them just like any other HTML tag.
  2. HTML Templates – These let you define fragments of markup that stay consistent across web pages with the ability to inject dynamic content using JavaScript.
  3. Shadow DOM – This is designed to abstract all the complexities from the markup by defining functional boundaries between the DOM tree and the subtrees hidden behind a shadow root.
  4. HTML Imports – Similar to import one CSS file into another, these allow you to include and reuse HTML documents in other HTML documents.

What is Polymer?

The specifications introduced above are quite new and it is hardly surprising to know that browser support is not very good. But, thanks to the Polymer library, created by the awesome folks at Google, we can use all these features in modern browsers today. Polymer provides a set of polyfills that enables us to use web components in non-compliant browsers with an easy-to-use framework. Polymer does this by:

  1. Allowing us to create Custom Elements with user-defined naming schemes. These custom elements can then be distributed across the network and used by others with HTML Imports.
  2. Allowing each custom element to have its own template accompanied by styles and behavior required to use that element.
  3. Providing a suite of ready-made UI and non-UI elements to use and extend in your project.

Note: X-Tag is a similar project by Mozilla that brings the promise of Custom Elements to all modern browsers.

This article primarily focuses on using visual elements that are part of the Polymer library. The elements collection is divided into two sections:

  1. Core Elements – These are a set of visual and non-visual elements designed to work with the layout, user interaction, selection, and scaffolding applications.
  2. Paper Elements – Implements the material design philosophy launched by Google recently at Google I/O 2014, and these include everything from a simple button to a dialog box with neat visual effects.

Installing Polymer

The recommended way to install Polymer (v0.3.4) is through Bower. Bower is a package manager that manages dependencies for your project. If you are not familiar with Bower, then I recommend you read the instructions on its website to learn how to install and get started with it.

Assuming you have a project folder setup with a bower.json file, you can install the latest version of Polymer by running the following via the command line:

bower install --save Polymer/polymer

This will install the Polymer library and the platform polyfills inside the bower-components folder.

bower_components/
├── core-component-page
├── platform
└── polymer

Note: --save will add the package as a dependency to the bower.json file. This is useful when you want to update the packages used in your project.

Since installing Polymer, you can start by creating the index.html file in the root of your project folder.
.
├── bower_components/
├── bower.json
└── index.html

Add the platform.js polyfill in the <head> of your document and then you’ll be ready to use predefined custom elements in your documents.

<script src="bower_components/platform/platform.js"></script>

Using Custom Elements

Using custom elements in your markup typically involves the following steps:

  1. Download the Custom Element package via Bower.
  2. Import the corresponding .html file in your document.
  3. Use the custom element markup anywhere in your document.

In this example, we’ll experiment with the paper-input custom element and use it in our HTML page. You can install paper-input directly from Bower and it will automatically download other required dependencies.

bower install --save Polymer/paper-input

Before you use any custom elements in your page, you need to import the corresponding .html file:

<link href="bower_components/paper-input/paper-input.html" rel="import">

Now you can use the paper-input element anywhere inside the <body> tag:

<paper-input></paper-input>

There are quite a few variations possible with the vast number of attributes accompanying this custom element. The component page has the complete list of attributes that can be used with paper-input. With the help of the Polymer Designer Tool, I have created a demo page that provides example usage of various attributes.

paper-input demo

The one that I particularly like is the Floating Label technique, which has become very popular and a number of people have written about it. All those techniques are great but none could be simpler than just adding an attribute to the tag:

<paper-input floatingLabel label="Floating Label"></paper-input>

Styling Custom Elements

Custom elements are first-class HTML elements, which means that they can be styled via CSS and scripted via JavaScript just like any other HTML element.

For instance, to style our paper-input custom element, we can use the tag name as the selector to style all paper-input elements:

paper-input { 
    width: 400px;
    height: 15px;
}

Or style a bunch of them with the same class:

.first-name {
    width: 400px;
    height: 15px;
}

Or target a specific paper-input element with an ID:

$('#first-name').addClass('show');

There may be instances when you want to override the default styles of the custom element that may not necessarily be affected by the above selectors. This happens because the markup that makes up a custom element lives under the Shadow DOM, which remains immune to the styles directly applied to the custom element.

Thankfully, Polymer provides the ::shadow pseudo-element and the /deep/ combinator to pierce through the boundaries of the Shadow DOM and allow us to style elements under different shadow trees from outside the custom element.

For example, let’s say you want to override the default blue scheme of our paper-input to green.

Paper Input Shadow DOM

Looking at the markup of the custom element beneath the Shadow DOM, you can figure out that you need to alter the styles of .focusedColor to change the color scheme.

So, paper-input::shadow will match #shadow-root within the paper-input element. From there, you can write a normal descendant selector to target individual elements:

paper-input::shadow .focusedColor {
    color: white;
    background: red;
}

Similarly, the /deep/ combinator can completely ignore all shadow boundaries, letting you cross into any number of shadow trees to reach the target element:

paper-input /deep/ .focusedColor { 
    color: white;
    background: red;
}

Note: In this example, both ::shadow and /deep/ would work the same way. /deep/ will become useful when you want to target descendent elements of custom elements that live under concentric shadow boundaries.

The combination of ::shadow and /deep/ selectors lets you style elements across the component. But at the same time, styling custom elements from outside does add layers of cancelled overridden styles that were previously authored for the custom element.

Overridden styles

Browser Compatiblity

Polymer aims to support the latest version of evergreen browsers (meaning browsers that auto-update). In practice, the paper-input custom element should work the same in recent versions of all major browsers.

This has a caveat though, because our specific styles to override the default color scheme of the paper-input element do not work as expected in Safari. In case you aren’t aware, Apple has removed Shadow DOM from Safari, that means ::shadow and /deep/ represent invalid selectors for Safari, which forces the CSS parser to completely ignore the rule sets defined with those selectors.

Safari Devtools Screenshot for Custom Element

As it stands, the latest version of Safari (v7.0.4) exposes the elements inside the Shadow DOM to the outer level, which means we can use standard CSS descendant selectors to achieve the same effect.

paper-input .focusedColor { 
    color: white;
    background: red;
}

Note: Do not combine rule sets with selectors for other browsers with this one, otherwise Safari will ignore the entire rule set.

Too many HTTP requests?

It’s tough to imagine that using a simple element like paper-input would result into so many HTTP requests!

Chrome Developer Tools Screenshot showing Too many HTTP requests

This can be attributed to the modular nature of Polymer, where each component is composed of several other functional units with each unit possessing the capability to run independently.

Using these custom elements on a large scale web application could drastically degrade the network performance of your website. To tackle this problem, the Polymer team built Vulcanize. Vulcanize inlines all your HTML imports, flattens their dependencies, and produces an output that generates far fewer network requests.

Addy Osmani has written an in-depth article about Vulcanize on the Polymer blog, describing the process of concatenation and inlining assets using Vulcanize.

It is important not to forget that Polymer is still in developer preview and is continuously being worked on by the community (you can contribute too!).

That being said, this shouldn’t stop us from building today’s web applications with the powerful features of Polymer and web components.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

  • Aurelio De Rosa

    Good article, well done.

  • tranhueminh89

    I like it .Thanks

  • Таканов Маекава

    Good introduction. I heard of Polimer from my colleagues several times, but didn’t understand what it was. Thanks.

  • nadimtuhin

    Liked it

  • http://viii.in Vinay Raghu

    Very detailed introduction to the topic. Thanks!

  • Jan Nahody

    ::shadow seem not work inside actual chrome (38-41). Don’t know why?
    /deep/ work fine.

  • James Hibbard

    After running:
    bower install –save Polymer/polymer
    you need to run:
    bower install –save Polymer/platform
    Maybe this changed since the article was published.

  • http://ali.md/ Ali Mihandoost

    Very nice, please update for polymer 1.0 and specially describe polymer starter kit and gulp task build to solve many problems

  • http://www.kenguie.com Ken Guie

    Nice intro article, I’ve been using more Node and NPM the last year, hoping there is a way to use npm instead but shouldn’t matter – thanks for writing!

    • Robi Ray

      Ken,
      That’s because you are trying to open the HTML directly from the browser. Get it served from an HTTP server & it should resolve.

      Regards.

  • geniium

    Thanks for sharing!

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.