1 of 37

Introduction to

Web

Components

London Polymer Meetup, April 2016

@marco_ciampini

2 of 37

3 of 37

The past

4 of 37

5 of 37

6 of 37

7 of 37

we’re lacking

functional encapsulation within

the Web Platform

8 of 37

Enter

Web Components

9 of 37

!==

10 of 37

Teach new elements

to the browser

11 of 37

  • In the DOM tree with the rest of the other elements
  • Accessed and manipulated with DOM APIs
  • Attributes and methods

  • Modularity and reusability
  • Easier to maintain
  • Framework agnostic (the DOM is the framework)

Teach new elements

to the browser

12 of 37

HTML

Imports

W3C draft

Custom

Elements

W3C draft

Shadow

DOM

W3C draft

HTML

Templates

W3C spec

13 of 37

Custom Elements

“enabling the author to define and use new types of DOM elements in a document”

W3C draft

14 of 37

Custom tag

<flag-icon country="uk">

</flag-icon>

Type extension

(non normative)

  • Complete control on implementation
  • Developer needs to take care of semantics and a11y
  • Inherits semantics and behaviour from extended element

<button is="plastic-button">

Click Me!</button>

15 of 37

Custom Elements

Extend HTMLElement

Are backed by a JS object. Constructor and prototype are defined by the user

Lifecycle callbacks

Observed attributes

16 of 37

class FlagIcon extends HTMLElement {� constructor() {super(); this._countryCode = null;}�� static get observedAttributes() {return ['country'];}�� attributeChangedCallback(name, oldVal, newVal) {� this._countryCode = newVal;

this._updateRendering();� }�� connectedCallback() { this._updateRendering(); }�� get country() { return this._countryCode; }� set country(v) { this.setAttribute('country', v); }�� _updateRendering() {� // Check this.ownerDocument.defaultView, and avoid

// any work if there is no browsing context� }�}��customElements.define('flag-icon', FlagIcon);

Old syntax

New syntax (not implemented yet by browsers)

var proto = Object.create(

HTMLElement.prototype);��proto.createdCallback =

function() {...};�

proto.attachedCallback =

function() {...};�

proto.attributeChangedCallback =

function(name, oldV, newV) {...};�

proto._updateRendering =

function() {...};��var flagIcon =

document.registerElement(

'flag-icon',

{prototype: proto});

17 of 37

HTML Templates

“declare inert HTML subtrees that can be cloned and inserted in the document at runtime”

W3C spec

18 of 37

<template>

[documentFragment]

</template>

[documentFragment]

...

...

[documentFragment]

[documentFragment]

Not

rendered

Rendered

19 of 37

<table><tbody><template id="row"><tr><td>Hi</td><td></td></tr></template></tbody></table>��<script>� var data = ['bar', 'foo'];� var template = document.querySelector('#row');� var clone, cells;�� for (var i = 0; i < data.length; i += 1) {� clone = template.content.cloneNode(true);� cells = clone.querySelectorAll('td');� cells[1].textContent = data[i];� template.parentNode.appendChild(clone);� }�</script>

20 of 37

HTML Imports

“a way to include and reuse HTML documents in other HTML documents”

W3C draft

21 of 37

require() for the web

Render blocking if not async

load() and error() events

<link rel="import" href="/imports/file.html">

22 of 37

Shadow DOM

“..combining multiple DOM trees into one hierarchy, and how these trees interact with each other within a document..”

W3C draft

23 of 37

core of the Web Components standards

encapsulate element implementation into a separate DOM tree

DOM APIs (including event retargeting) and styles are scoped within a shadow tree and not accessible by the

host document

Shadow DOM

24 of 37

docu

ment

shadow

host

shadow

root

shadow tree

document tree

Shadow boundaries

hosts

Light DOM

Shadow DOM

25 of 37

Distribution and slotting

“conceptually, slots are holes in a shadow DOM that will be filled by children of its host element”

26 of 37

Bonus Round:

CSS scoping &

CSS variables

W3C draft

27 of 37

@scope, :scope, :scope-context()

Create scoping style rules and access ancestors

:host, :host(), :host-context()

Select shadow host on its normal (Light DOM) context

::content, ::content() (renamed to ::slotted())

Select slot-assigned content

Deprecated:

>>>, ::shadow, /deep/

CSS scoping rules

28 of 37

:root {� --base-text-color: #333; �}��body {� color: var(--base-text-color, black);�}

CSS Variables

29 of 37

:root {� --header-styles: {

font-size: 3em;

margin: 0 auto 2em;

}�}��h1 {� @apply(--header-styles);�}

CSS Mixins

30 of 37

Using Web Components today

31 of 37

Chrome/

Opera

Firefox

Safari

Edge

Templates

Stable

Stable

8

13

HTML Imports

Stable

On hold

Not considering

Not considering

Custom Elements

Stable

Flag

(unstable)

In development

Prototyping

Shadow DOM

Stable

Flag

(unstable)

Technology

Preview

Prototyping

Browser support

32 of 37

webcomponents.js

All polyfills

webcomponents-lite.js

No Shadow DOM

33 of 37

Shadow DOM polyfill is slow

34 of 37

What’s next

Reworking HTML Imports

Declarative <shadow-dom> ?

Accessibility primitives

CSS parts styling

And more...

35 of 37

Web Components libraries

36 of 37

Useful links

37 of 37

cheers

@marco_ciampini