An intro to web components with otters

everyone keeps talking about web components, but huh?

I work on a library called Polymer, which helps you write web components faster and easier. This is awesome, but it’s only awesome if you (yes, YOU) know what a web component is, and know that you want to write one. So here’s a story about what these things are and teaches you how to use them without showing you 10 pages of docs and getting you to install tools and CLIs. Maybe it’s for you. Maybe it isn’t. In either case, it has otters.

Why should you care?

Web components aren’t a new library or framework, they’re a new browser feature, and they let you write encapsulated and reusable components (more details). If you’ve ever used an <input> element, I like to think of it as the OG web component, because it’s exactly that. The thing is that before web components came around, you had to wait on all browsers to agree on a new element (like, a date picker). And even after they agreed on a new element, it took them yeaaaaars to implement it. <input type="date"> was drafted in 2011 – today, 6 years later, not all browsers have implemented it! With web components, web developers get to write such elements, so that you don’t have to wait for 10 years before all browsers agree that they should implement a date picker. P cool, right?

so i can write <emoji-picker>, yay!

You write web components in ES6 JavaScript. Polymer is a JavaScript library that’s like jQuery for web components – you import it, it gives you a bunch of helper functions and saves you writing a lot of boilerplate code.

Also, bad habit: people (and me, I am those people) tend to use “custom element” and “web component” interchangeably. If you’re pedantic, they mean different things. Don’t be pedantic, it makes the otters sad.

sad otter because it's getting well-actuallied

Thinking about your app

If you’re starting to think about using web components in your app, there’s basically 2 situations you could be in, and I tend to reason about each differently

  1. I want to use someone else’s web component in my app
  2. I want to write a web component to use in my app

There’s other things that you might eventually care about, such as making your application production ready, and improving its performance. They are super important topics, but if you’ve never used a web component before, they’re also not the most important topics for you right now.

is this magic? nah it's prolly just undocumented code

Where do web components live?

in otter space!

Web components tend to have dependencies on other web components, so you need a package manager to herd all them cats. Most of the web components out there use bower. Another popular one is npm – you could think of npm as a package manager for your server code and bower for your client, and it wouldn’t be entirely incorrect.

The reason why you need a package manager and not just “download this element in a zip file” is that unless that element is really simple, it might have dependencies, and they’ll have dependencies, and that’s a thing for machines and not otters. If you really don’t want to use bower, then you’ll have to sort out flattening your dependency tree on your own using something like webpack. This is not the tutorial for you.

If you look up bower on the web you’ll hear things like “but bower is deprecated now” (which is true, but it’s also been unmaintained for like a year and it worked fine, so nothing is really new on that front) and “but why not npm” (because you can only have one version of the same web component in your app, and that’s hard if your dependency tree is not flat. You probably don’t actually care this).

attenshun attenshun installation instructions

To install bower, a package manager, you must first install npm, a package manager. Take a moment for a concerned sigh, but install it anyway. Upshot: I promise this is the only tool I will ask you to install.

If you want to find otter web components, is a universal catalog of web components (but not a package manager, because that would be cray). Go check it out.

Polyfills and you

anotter digression

Not all browsers implement features at the same rate, which means while you’re waiting for them to catch up, you need to care about polyfills. Fun fact: you know how when you have a hole in a wall, you have to put spackling paste in it to make the wall look like a wall again? Polyfilla is a brand of spackling, and that’s exactly what a polyfill is – it fills a hole in the browser, so that it looks even from the outside.

You have two choices:

in your applications’s <head> tag whadya think? we otter get to the code!

1. I want to use someone else’s web component in my app

Ok cool, so here we are. You have a web site, and you want to use someone else’s web widget in it. Let’s say that thing is paper-button which is a super fancy looking Material Design button. It’s beauty and it’s grace, it’s Miss United States.

Here is a glitch app if you want to follow along at home. Glitch is an online code editor, where you can build apps and modify other people’s – which is why it’s great for this example!

We need to do 3 things:

1. Install the web component

Status check

Right now you should have a bower_components folder created, that contains a whole bunch of folders, one of which is called paper-button.

2. Import it in the app

This basically tells the browser where to find the definition for what this paper-button tag is.

Much like how you import a CSS stylesheet with

<link rel="stylesheet" href="/style.css">

You import a web component with an HTML import:

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

3. Insert it somewhere in the app

Drop a <paper-button>Click me</paper-button> somewhere in your html page.

Status check

Your index.html should basically look like this:

<!DOCTYPE html>
    <!-- Load the polyfill so that the demo works everywhere -->
    <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>

    <!-- Import the custom element so that the browser knows what it means -->
    <link rel="import" href="/bower_components/paper-button/paper-button.html">
    <h1>Oh, hi there</h1>
    <p>Have you seen this fancy button?</p>

    <!-- Use the custom element! -->
    <paper-button>Click me</paper-button>

See that line about loading the webcomponents-lite polyfill? That’s the bit that makes the demo work in browsers that don’t have web components yet 😎. If you want to see what your app looks like without the polyfill, just comment out that line and open your app in something like Firefox! It’s a good thing to try out.

If we run that demo, it should look like this, plus or minus some copy and styles that I’ve added:

Now, say it together with the otters! bower summary

You could, of course, add JavaScript to that custom element, like you would with any other <button> or <input>. I could’ve added something like this:

document.querySelector('paper-button').addEventListener('click', function() {
  alert('you did a click!');

2. I want to write a web component to use in my app

Now that we know how to import someone else’s custom element, let’s write our own! Up until now we haven’t actually talked about Polymer at all. You can totally write web components without Polymer; you’ll just have to write a lot more boilerplate, and I don’t want that to turn you off web components.

The Polymer site actually has an awesome getting started tutorial, if you’d rather read that. But while I have you here, you’ll get the otter way.

In Polymer, every custom element is like a taco (bear with me). There’s something called a dom-module (which is actually a custom element itself) that holds 2 things in it:

  1. the <template>, or what your element looks like (html and css). A <template> is an HTML element that’s inert – when the browser sees it, it skips it and doesn’t render it
  2. a <script>, which is what your element does

Sidebar: This is one of the advantages of using Polymer – without Polymer, you’d have to construct all your HTML and CSS in JavaScript, and somehow add it to your custom element. Polymer makes it easier for you to point at an implementation, and at a bunch of HTML/CSS and say “that look goes with that code”.

We add all our code to an .html file (because remember: we’re going to do an HTML import to bring it in our app later). It ends up looking like this:

<dom-module id="my-element">
    <!-- Any CSS your element needs for styling -->
      /* This is a special selector that styles the element itself */
      :host { ... }
      /* Use the usual CSS selectors for its children */
      p { color: tomato; }

    <!-- that <p> style there applies here -->
    <p>I should be a nice red!</p>

    // Every custom element is an ES6 class.
    // This is the implementation of the element.
    class MyElement extends Polymer.Element {

    // Every custom element needs to be registered.
    // This tells the browser that the <happy-thing>
    // tag uses _this_ implementation.
    customElements.define(, MyElement);

I tend to put one element per html file, and then name the file after the tag of the element, so I can keep track of it. I would save that into a my-element.html file, and then import it in our app, just as before with:

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

Now, what goes inside your custom element is really up to you. The way I write elements is

As a slightly more complicated example, I made a <happy-thing> element in this glitch app (check out the code). It basically takes whatever content you give to it, and when you hover over, it does a little shimmy animation:

I also made that element with plain JavaScript, without Polymer, if you want to compare it. You’ll notice the second example has a lot more boilerplate code, which Polymer abstracted out for you.

That’s all there is!

I hope this helped! I’m going to write another post in more detail about actually getting started with Polymer, and what kind of things you can do with it soon! In the meantime, here’s some other links to get you going:

let me know if this was useful to you! cause i'm otter here

👋 See you soon, new web component friends!

« Polymer 2.x Cheat Sheet PWAs with Polymer: a checklist »