Web Components

HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world

<body> HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world </body>

<body> <main> HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world </main> </body>

<body> <main> <h1> ✘ HURRICANE </h1> by Bob Dylan and Jacques Levy Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world </main> </body>

<body> <main> <h1> Hurricane </h1> by Bob Dylan and Jacques Levy h1 { Here comes the story of the Hurricane text-transform:The uppercase; man the authorities came to blame } For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world </main> </body>

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> Hurricane A footer typically contains information Here comes the story of the Hurricane about its section as who wrote it, The man the authorities came tosuch blame documents, copyright For somethin’links that to he related never done data, the like. Put in a prison cell,and but one time he could-a been The champion of the world </main> </body>

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> Hurricane footer Here comes the story of the Hurricane { The man the authorities came to blame font-style: italic; For somethin’ that he never done } Put in a prison cell, but one time he could-a been The champion of the world </main> </body>

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world </p> </main> </body> Hurricane

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> Here comes the story of the Hurricane <br/> The man the authorities came to blame <br/> For somethin’ that he never done <br/> Put in a prison cell, but one time he could-a been <br/> The champion of the world </p> </main> </body> Hurricane

HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world

HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world

HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> Here comes the story of the Hurricane The man the authorities came to blame For somethin’ that he never done Put in a prison cell, but one time he could-a been The champion of the world </p> </main> </body> Hurricane

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> <div> Here comes the story of the Hurricane </div> <div> The man the authorities came to blame </div> <div> For somethin’ that he never done </div> <div> Put in a prison cell, but one time he could-a been </div> <div> The champion of the world </div> </p> </main> </body> Hurricane ✘

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> <span> Here comes the story of the Hurricane </span> <span> The man the authorities came to blame </span> <span> For somethin’ that he never done </span> <span> Put in a prison cell, but one time he could-a been </span> <span> The champion of the world </span> </p> </main> </body> Hurricane

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> <span> Here comes the story of the Hurricane </span> <span> The man the authorities came to blame </span> <span> For somethin’ that he never done </span> span <span> Put in a prison cell, but one time he could-a been </span> { <span> The champion of the world </span> display: block; </p> } </main> </body> Hurricane ✘

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> class=”line”> Here comes the story of the Hurricane </span> class=”line”> The man the authorities came to blame </span> class=”line”> For somethin’ that he never done </span> class=”line”> Put in a prison cell, but one time he could-a been </span> class=”line”> The champion of the world </span> </p> </main> </body> Hurricane <span <span <span <span <span

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> class=”line”> Here comes the story of the Hurricane </span> class=”line”> The man the authorities came to blame </span> class=”line”> For somethin’ that he never done </span> .line class=”line”> Put in a prison cell, but one time he could-a been </span> { class=”line”> The champion of the world </span> display: block; </p> } </main> </body> Hurricane <span <span <span <span <span

HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane / The man the authorities came to blame / For somethin’ that he never done / Put in a prison cell, but one time he could-a been / The champion of the world

HURRICANE by Bob Dylan and Jacques Levy Here comes the story of the Hurricane / The man the authorities came to blame / For somethin’ that he never done / Put in a prison cell, but one time he could-a been / The champion of the world .line:not(:last-child)::after { content: ” / “; }

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> class=”line”> Here comes the story of the Hurricane </span> class=”line”> The man the authorities came to blame </span> class=”line”> For somethin’ that he never done </span> class=”line”> Put in a prison cell, but one time he could-a been </span> class=”line”> The champion of the world </span> </p> </main> </body> Hurricane <span <span <span <span <span

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> <l> Here comes the story of the Hurricane </l> <l> The man the authorities came to blame </l> <l> For somethin’ that he never done </l> <l> Put in a prison cell, but one time he could-a been </l> <l> The champion of the world </l> </p> </main> </body> Hurricane

Custom Elements

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> <x-l> Here comes the story of the Hurricane </x-l> <x-l> The man the authorities came to blame </x-l> <x-l> For somethin’ that he never done </x-l> <x-l> Put in a prison cell, but one time he could-a been </x-l> <x-l> The champion of the world </x-l> </p> </main> </body> Hurricane

<body> <main> <h1> </h1> <footer> by Bob Dylan and Jacques Levy </footer> <p> <x-l> Here comes the story of the Hurricane </x-l> <x-l> The man the authorities came to blame </x-l> <x-l> For somethin’ that he never done </x-l> x-l <x-l> Put in a prison cell, but one time he could-a been </x-l> { <x-l> The champion of the world </x-l> display: block; </p> padding-left: 1em; </main> text-indent: -1em; </body> } Hurricane

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

Three bodies lyin’ there does Patty see And another man named Bello, movin’ around mysteriously “I didn’t do it,” he says, and he throws up his hands “I was only robbin’ the register, I hope you understand I saw them leavin’,” he says, and he stops “One of us had better call up the cops” And so Patty calls the cops…

Three bodies lyin’ there does Patty see And another man named Bello, movin’ around mysteriously “I didn’t do it,” he says, and he throws up his hands “I was only robbin’ the register, I hope you understand I saw them leavin’,” he says, and he stops “One of us had better call up the cops” And so Patty calls the cops…

Three bodies lyin’ there does Patty see And another man named Bello, movin’ around mysteriously “I didn’t do it,” he says, and he throws up his hands “I was only robbin’ the register, I hope you understand I saw them leavin’,” he says, and he stops “One of us had better call up the cops” And so Patty calls the cops…

Three bodies lyin’ there does Patty see And another man named Bello, movin’ around mysteriously “I didn’t do it,” he says, and he throws up his hands “I was only robbin’ the register, I hope you understand I saw them leavin’,” he says, and he stops “One of us had better call up the cops” And so Patty calls the cops…

Three bodies lyin’ there does Patty see And another man named Bello, movin’ around mysteriously “I didn’t do it,” he says, and he throws up his hands “I was only robbin’ the register, I hope you understand I saw them leavin’,” he says, and he stops “One of us had better call up the cops” And so Patty calls the cops…

x-l { display: block; padding-left: 1em; text-indent: -1em; Three bodies lyin’ there does Patty see hanging-punctuation: first allow-end last; And another man named Bello, movin’ around mysteriously } “I didn’t do it,” he says, and he throws up his hands “I was only robbin’ the register, I hope you understand I saw them leavin’,” he says, and he stops “One of us had better call up the cops” And so Patty calls the cops…

hanging-punctuation ✘ ✘ ✘ ✘ ✘

for (var xlElements = document.querySelectorAll(‘x-l’), l = xlElements.length, i = 0; i < l; i++) { if (/^([„“]+)/.test(xlElements[i].innerHTML)) { xlElements[i].classList.add(‘hanging-punctuation-start’); } }

.hanging-punctuation-start for { (var xlElements = document.querySelectorAll(‘x-l’), l = xlElements.length, text-indent: -1.42em;i = 0; i < l; i++) { } if (/^([„“]+)/.test(xlElements[i].innerHTML)) { xlElements[i].classList.add(‘hanging-punctuation-start’); } } ✘

for (var xlElements = document.querySelectorAll(‘x-l’), l = xlElements.length, i = 0; i < l; i++) { xlElements[i].innerHTML = xlElements[i].innerHTML .replace(/^([„“’]+)/, ‘<span class=”hanging-punctuation-start”>$1</span>’); }

x-l { display: block; padding-left: 1em; -1em; for (var xlElements = text-indent: document.querySelectorAll(‘x-l’), position: l = xlElements.length, i = 0; relative; i < l; i++) } { xlElements[i].innerHTML = xlElements[i].innerHTML .hanging-punctuation-start .replace(/^([„“’]+)/, { ‘<span class=”hanging-punctuation-start”>$1</span>’); position: absolute; right: 100%; text-align: right; }

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); XLElementPrototype.createdCallback = function() { this.innerHTML = this.innerHTML.replace(/^([„“’]+)/, ‘<span class=”hanging-punctuation-start”>$1</span>’); } var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

Shadow DOM

<input placeholder=”…”> <input type=”range”> <audio>

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); XLElementPrototype.createdCallback = function() { this.innerHTML = this.innerHTML.replace(/^([„“’]+)/, ‘<span class=”hanging-punctuation-start”>$1</span>’); } var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); XLElementPrototype.createdCallback = function() { var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, ‘<span class=”hanging-punctuation-start”>$1</span>’); var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

x-l { var XLElementPrototype =display: Object.create(HTMLSpanElement.prototype); block; padding-left: 1em; XLElementPrototype.createdCallback function() text-indent:= -1em; { position: relative; var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, .hanging-punctuation-start ‘<span class=”hanging-punctuation-start”>$1</span>’); { } position: absolute; right: 100%; var XLElement = document.registerElement(‘x-l’, { text-align: right; prototype: XLElementPrototype } });

x-l { var XLElementPrototype =display: Object.create(HTMLSpanElement.prototype); block; padding-left: 1em; XLElementPrototype.createdCallback function() text-indent:= -1em; { position: relative; var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, x-l::shadow .hanging-punctuation-start ‘<span class=”hanging-punctuation-start”>$1</span>’); { } position: absolute; right: 100%; var XLElement = document.registerElement(‘x-l’, { text-align: right; prototype: XLElementPrototype } });

x-l { var XLElementPrototype =display: Object.create(HTMLSpanElement.prototype); block; padding-left: 1em; XLElementPrototype.createdCallback function() text-indent:= -1em; { position: relative; var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, x-l::shadow .hanging-punctuation-start It’s been suggested to ‘<span class=”hanging-punctuation-start”>$1</span>’); { remove this feature. } position: absolute; right: 100%; var XLElement = document.registerElement(‘x-l’, { text-align: right; prototype: XLElementPrototype } });

x-l { var XLElementPrototype =display: Object.create(HTMLSpanElement.prototype); block; padding-left: 1em; XLElementPrototype.createdCallback function() text-indent:= -1em; { position: relative; var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, x-l /deep/ .hanging-punctuation-start ‘<span class=”hanging-punctuation-start”>$1</span>’); { } position: absolute; right: 100%; var XLElement = document.registerElement(‘x-l’, { text-align: right; prototype: XLElementPrototype } });

x-l { var XLElementPrototype =display: Object.create(HTMLSpanElement.prototype); block; padding-left: 1em; XLElementPrototype.createdCallback function() text-indent:= -1em; { position: relative; var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, x-l >>> .hanging-punctuation-start ‘<span class=”hanging-punctuation-start”>$1</span>’); { } position: absolute; right: 100%; var XLElement = document.registerElement(‘x-l’, { text-align: right; prototype: XLElementPrototype } });

x-l { var XLElementPrototype =display: Object.create(HTMLSpanElement.prototype); block; padding-left: 1em; XLElementPrototype.createdCallback function() text-indent:= -1em; { position: relative; var root = this.createShadowRoot(); } It’s currently disputed root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, x-l >>> .hanging-punctuation-start whether this combinator ‘<span class=”hanging-punctuation-start”>$1</span>’); { should exist. } position: absolute; right: 100%; var XLElement = document.registerElement(‘x-l’, { text-align: right; prototype: XLElementPrototype } });

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); XLElementPrototype.createdCallback = function() { var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, ‘<span class=”hanging-punctuation-start”>$1</span>’); var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); XLElementPrototype.createdCallback = function() { var root = this.createShadowRoot(); } root.innerHTML = this.innerHTML.replace(/^([„“’]+)/, ‘<span class=”hanging-punctuation-start”>$1</span>’) + ‘<style>.hanging-punctuation-start { position: absolute;\ right: 100%; text-align: right }</style>’; var XLElement = document.registerElement(‘x-l’, {

Templates

<template id=”hanging-punctuation-start-template”> <span class=”hanging-punctuation-start”></span> <style> .hanging-punctuation-start { position: absolute; right: 100%; text-align: right; } </style> </template>

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); XLElementPrototype.createdCallback = function() { var result = /^([„“’]+)/.exec(this.innerHTML); if (result) { var template = document.querySelector(‘#hanging-punctuation-start-template’); template.content.querySelector(‘.hanging-punctuation-start’).innerHTML = result[0]; var clone = document.importNode(template.content, true); var root = this.createShadowRoot(); root.innerHTML = this.innerHTML.substr(result[0].length); root.appendChild(clone); } } var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

HTML Imports

hanging-punctuation-start-template.html <template id=”hanging-punctuation-start-template”> <span class=”hanging-punctuation-start”></span> <style> .hanging-punctuation-start { position: absolute; right: 100%; text-align: right; } </style> </template>

<link rel=”import” href=”hanging-punctuation-start-template.html”>

var XLElementPrototype = Object.create(HTMLSpanElement.prototype); XLElementPrototype.createdCallback = function() { var result = /^([„“’]+)/.exec(this.innerHTML); if (result) { var link = document.querySelector(‘link[rel=”import”]’); var template = link.import.querySelector(‘#hanging-punctuation-start-template’); template.content.querySelector(‘.hanging-punctuation-start’).innerHTML = result[0]; var clone = document.importNode(template.content, true); var root = this.createShadowRoot(); root.innerHTML = this.innerHTML.substr(result[0].length); root.appendChild(clone); } } var XLElement = document.registerElement(‘x-l’, { prototype: XLElementPrototype });

Templates HTML Imports Custom Elements Shadow DOM ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✘ ✘ ✘ ✔ ✘ ✘ ✘ ✔ ✘ ✘ ✘

progressive enhancement

An escalator can never break, it can only become stairs. You would never see an “Escalator Temporarily Out Of Order” sign, just “Escalator Temporarily Stairs. Sorry for the convenience. We apologize for the fact that you can still get up there.” —Mitch Hedberg

There’s a common misconception that progressive enhancement means that you’ll spend your time dealing with older browsers, but in fact the opposite is true. Putting the basic functionality into place doesn’t take very long at all. And once you’ve done that, you’re free to spend all your time experimenting with the latest and greatest browser technologies, secure in the knowledge that even if they aren’t universally supported yet, that’s okay: you’ve already got your fallback in place. —Jeremy Keith

The key to thinking about web development this way is realising that there isn’t one final interface— there could be many, slightly different interfaces depending on the properties and capabilities of any particular user agent at any particular moment. And that’s okay. Websites do not need to look the same in every browser. —Jeremy Keith

Once you truly accept that, it’s an immensely liberating idea. Instead of spending your time trying to make websites look the same in wildly varying browsers, you can spend your time making sure that the core functionality of what you’re building works everywhere, while providing the best possible experience for more capable browsers. —Jeremy Keith

<table> <caption>Bruce Springsteen’s studio albums</caption> <thead> <tr> <th>title</th> <th>release date</th> </tr> </thead> <tbody> <tr> <td>Greetings from Asbury Park, N.J.</td> <td> <time>1973-01-05</time> </td> </tr>

<table sortable> <caption>Bruce Springsteen’s studio albums</caption> <thead> <tr> <th>title</th> <th sorted>release date</th> </tr> </thead> <tbody> <tr> <td>Greetings from Asbury Park, N.J.</td> <td> <time>1973-01-05</time> </td> </tr> ▼

<table sortable> ✘ ✘ ✘ ✘ ✘

✘ <x-sortable-table> <caption>Bruce Springsteen’s studio albums</caption> <thead> <tr> <th>title</th> <th sorted>release date</th> </tr> </thead> <tbody> <tr> <td>Greetings from Asbury Park, N.J.</td> <td> <time>1973-01-05</time> </td> </tr> ▼

<table is=”x-sortable-table”> <caption>Bruce Springsteen’s studio albums</caption> <thead> <tr> <th>title</th> <th sorted>release date</th> </tr> </thead> <tbody> <tr> <td>Greetings from Asbury Park, N.J.</td> <td> <time>1973-01-05</time> </td> </tr> ▼

var XSortableTableElementPrototype = Object.create(HTMLTableElement.prototype); var XSortableTableElement = document.registerElement(‘x-sortable-table’, { prototype: XSortableTableElementPrototype, extends: ‘table’ }); → http://codepen.io/gunnarbittersmann/pen/XXwZpP

Custom Elements Shadow DOM Templates HTML Imports

Custom Elements Templates Look Ma, no JS framework! Shadow DOM HTML Imports

AngularJS

<!DOCTYPE html> <html ng-app=”analogClockApp”> <head> <meta charset=”UTF-8”/> <link rel=”stylesheet” href=”analog-clock.css”/> </head> <body ng-controller=”AnalogClockCtrl”> <time analog-clock/> <script src=”angular.min.js”></script> <script src=”analogClockApp.js”></script> </body> </html>

analogClockTemplate.html <div class=”face”> <div class=”hour-hand” style=”transform: rotate({{ 30 * (now | date:’h’) + (now | date:’m’) / 2 }}deg)”></div> <div class=”minute-hand” style=”transform: rotate({{ 6 * (now | date:’m’) }}deg)”></div> <div class=”second-hand” style=”transform: rotate({{ 6 * (now | date:’s’) + (now | date:’m’) * 360 + (now | date:’h’) * 360 }}deg)”></div> </div>

.face { width: 250px; height: 250px; position: relative; background-position: left top; transform: translate(461px,51px) rotateX(46deg) rotateY(27deg) rotateZ(-38deg); } .hour-hand { width: 4%; height: 35%; background: hsl(0, 0%, 95%); position: absolute; left: 48%; top: 25%; transform-origin: center 71.43%; }

var analogClockApp = angular.module(‘analogClockApp’, []); analogClockApp.directive(‘analogClock’, function () { return { templateUrl: ‘analogClockTemplate.html’ }; });

analogClockApp.controller(‘AnalogClockCtrl’, function ($scope, $timeout) { $scope.now = ‘Loading…’; var updateTime = function () { $timeout(function () { $scope.now = new Date(); updateTime(); }, 1000); }; updateTime(); });

Web Components AngularJS

Web Components Hurricane Blinded by the Light written by Bob Dylan and Jacques Levy written by Bruce Springsteen Copenhagen Metro Escalators photo by Stig Nygaard, CC-BY-2.0