The Composable Web

with Web Components


@ryanseddon

Web Components is made up of Templates, Custom Elements, Shadow DOM and imports

Templates

<template>
  <h1>User</h1>
  <img src="avatar.jpg" />
  <script>console.log("user");</script>
</template>

Templates


JS Bin

Custom Elements

<x-reverse></x-reverse>

Custom Elements


Register Custom Element

var XReverse = document.registerElement('x-reverse');

Prototype Custom Element

var XReverse = document.registerElement('x-reverse', {
  prototype: Object.create(HTMLElement.prototype);
});

Lifecycle events


Custom Element FOUC?

x-reverse:unresolved {
  opacity: 0;
}
x-reverse {
  transition: opacity 0.5s;
  opacity: 1;
}
JS Bin

Shadow DOM

Shadow DOM


JS Bin

Shadow DOM elements


Shadow DOM CSS


Imports

<link rel="import" href="media-object.html">

Imports


Composability


A component should do one thing well

Unix philosophy

Emphasize building short, simple, clear, modular, and extendable code that can be easily maintained and repurposed by developers other than its creators.

— Wikipedia

Example

  •  
  •  
  •  
  •  
  •  
<media-object></media-object>
<media-object>
  <x-avatar></x-avatar>
</media-object>
<media-object>
  <img is="x-avatar" />
</media-object>
<media-object>
  <img is="x-avatar" />
  <mo-body></mo-body>
</media-object>
<media-object>
  <img is="x-avatar" />
  <mo-body>
    <mo-header></mo-header>
  </mo-body>
</media-object>
<media-object>
  <img is="x-avatar" />
  <mo-body>
    <mo-header></mo-header>
    <mo-content></mo-content>
  </mo-body>
</media-object>

x-avatar

document.registerElement('x-avatar', {
  prototype: Object.create(HTMLImageElement.prototype),
  extends: 'img'
});
var XAvatarPrototype = Object.create(HTMLImageElement.prototype);

XAvatarPrototype.createdCallback = function() {
  var data = this.dataset,
      username = data.username,
      service = data.service,
      url = 'http://avatars.io/' + service + '/' + username;
      
  this.src = url;
};
<img
  is="x-avatar"
  data-service="twitter"
  data-username="ryanseddon"
/>
XAvatarElementPrototype.getAvatarURL = function() {
  // Return avatars.io formatted url
};

XAvatarElementPrototype.attributeChangedCallback = function(attr) {
  this.src = this.getAvatarURL();
};

media-object

<link rel="import" href="x-avatar.html">

Register media-object, mo-body, mo-header, mo-content

document.registerElement('...');

Encapsulate styles

MediaObjectElementPrototype.createdCallback = function() {
  this.createShadowRoot().innerHTML = styles + '<content></content>';
}

That "styles" var

:host {
  display: flex;
}
::content [is="x-avatar"] {
  margin-right: 15px;
}
::content mo-body {
  flex: 1;
}

No classes


:host and ::content

JS Bin

Web Components API


Starts to get a little verbose but that's on purpose

extensiblewebmanifesto.org

Polymer media-object

<polymer-element name="media-object" noscript>
  <template>
    <!--// Shadow DOM -- >
    <link rel="stylesheet" href="media-object.css">
  </template>
</polymer-element>

<media-object> demo

Mozilla Brick

reusable UI components created to enable rapid development of cross-browser and mobile-friendly HTML5 web applications.

Composability in mind


Frameworks


Web Component issues

Conflicts and relationships


XML Namspacing

<namespace:media-object></namespace:media-object>

Dependency management


Accessibility, Performance & Security

...where pioneers and community-members of the Web Components ecosystem document web components best practices...

The goto place for
Web Components

Takeaways

Go forth & compose

@ryanseddon

Zendesk is hiring come talk to me