HTML with Superpowers

A presentation at An Event Apart Spring Summit in April 2021 in by Dave Rupert

Slide 1

Slide 1

Slide 2

Slide 2

Howdy, I’m Dave Rupert Work at Paravel in Austin, TX Co-host ShopTalk podcast with Chris Coyier W3C Web Components Community Group (member)

Slide 3

Slide 3

What are Web Components? “Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web pages and web apps.” –webcomponents.org

Slide 4

Slide 4

What are Web Components?

Slide 5

Slide 5

Design Systems

Slide 6

Slide 6

A Brief, Incomplete History of Web-based Component Systems 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016

Slide 7

Slide 7

What makes Web Components so unique?

Slide 8

Slide 8

4 native web technologies HTML <template> Custom Elements <custom-element> Shadow DOM “Encapsulation” HTML Imports ES Modules

Slide 9

Slide 9

Great. But… Are any companies actually using this?

Slide 10

Slide 10

[social validation slide]

Slide 11

Slide 11

According to Google… 12% of pages loaded in Chrome using Web Components

Slide 12

Slide 12

If they’re so great… Why am I not using them?!?

Slide 13

Slide 13

Perfectly valid question! 1. 2. 3. 4. Too low-level, designed for framework authors Marketing problem from heavy-handed advocacy Hard to invest in something unknown Not truly supported until very recently

Slide 14

Slide 14

Slow like brisket… Web Components will always be slower than HotNewFramework.js because they are Web Standards, but that slowness is what can make them a stable foundation to build on.

Slide 15

Slide 15

Slide 16

Slide 16

Slide 17

Slide 17

Using Web Components with HTML

Slide 18

Slide 18

Slide 19

Slide 19

JavaScript People who just want to write HTML and CSS

Slide 20

Slide 20

Assertion #1 Web Components bring us one step closer to writing HTML again.

Slide 21

Slide 21

Slide 22

Slide 22

<two-up>

Slide 23

Slide 23

<two-up> <two-up> <div><img src=”before.jpg” alt=”“></div> <div><img src=”after.jpg” alt=”“></div> </two-up> <script src=”path/to/two-up.js”></script>

Slide 24

Slide 24

Slide 25

Slide 25

A basic example <div class=”alert”> <img src=”path/to/icon_note.svg” alt=”” /> <p>Alert message goes here.</p> <button>Close</button> </div>

Slide 26

Slide 26

A basic example <custom-alert icon=”note”> <p>Alert message goes here.</p> </custom-alert> <script src=”path/to/custom-alert.js”></script>

Slide 27

Slide 27

A basic example

Slide 28

Slide 28

A basic example <custom-alert icon=”note”> <p>Alert message goes here.</p> <img src=”path/to/icon_note.svg” /> <slot></slot> <button>Close</button> </custom-alert>

Slide 29

Slide 29

Assertion #2 Web Components are great for Progressive Enhancement

Slide 30

Slide 30

I have strong opinions about podcast players

Slide 31

Slide 31

The native <audio> player

Slide 32

Slide 32

<podcast-player> <podcast-player> <audio src=”path/to/my.mp3” controls></audio> </podcast-player> <script type=”module” src=”path/to/podcast-player.js”></script>

Slide 33

Slide 33

<podcast-player>

Slide 34

Slide 34

<podcast-player>

Slide 35

Slide 35

<podcast-player>

Slide 36

Slide 36

Assertion #3 Web Components will let us make simpler, more accessible, and more maintainable websites.

Slide 37

Slide 37

Wait. Wait. Hold up. Wait. Are you saying Web Components would allow us to create and share accessible prebuilt components without the need for specific JavaScript libraries and overly complicated build processes?!

Slide 38

Slide 38

Yes. I am. That’s the vision.

Slide 39

Slide 39

Generic Components

Slide 40

Slide 40

<generic-tabs> <generic-tabs> <button slot=”tab”>About</button> <button slot=”tab”>Contact</button> <div slot=”panel”> <p>Lorem ipsum dolor sit amet….</p> </div> <div slot=”panel”> <p>Sed ut perspiciatis unde omnis….</p> </div> </generic-tabs>

Slide 41

Slide 41

<generic-tabs> <generic-tabs> <h2>About</h2> <div> <p>Sed ut perspiciatis unde …</p> </div> <h2>Contact</h2> <div> <p>Ut enim ad minima veniam…</p> </div> </generic-tabs>

Slide 42

Slide 42

!

Slide 43

Slide 43

Assertion #4 Web Components are a gateway to a new dimension.

Slide 44

Slide 44

Slide 45

Slide 45

<model-viewer> <script type=”module” src=”path/to/model-viewer.min.js”></script> <model-viewer src=”path/to/Astronaut.glb” alt=”A 3D model of an astronaut” auto-rotate camera-controls> </model-viewer>

Slide 46

Slide 46

<model-viewer>

Slide 47

Slide 47

Slide 48

Slide 48

Slide 49

Slide 49

<a-frame> <script src=”path/to/aframe.min.js”></script> <a-scene> <a-sphere position=”0 1.25 -5” radius=”1.25” color=”#EF2D5E”></a-sphere> <a-box position=”-1 0.5 -3” rotation=”0 45 0” width=”1” height=”1” depth=”1” color=”#4CC3D9”></a-box> <a-cylinder position=”1 0.75 -3” radius=”0.5” height=”1.5” color=”#FFC65D”></a-cylinder> <a-plane position=”0 0 -4” rotation=”-90 0 0” width=”4” height=”4” color=”#7BC8A4”></a-plane> <a-sky color=”#ECECEC”></a-sky> </a-scene>

Slide 50

Slide 50

Slide 51

Slide 51

Slide 52

Slide 52

How do you find cool Web Components? Me, personally? Poor work/life balance. You?

Slide 53

Slide 53

! Awesome Standalones

Slide 54

Slide 54

Summary of what’s good about Web Components ü Easy as HTML ü Great reusability ü Better experiences ü Progressively enhanced ü No build tools ü “Encapsulated”

Slide 55

Slide 55

Slide 56

Slide 56

Styling Web Components with CSS

Slide 57

Slide 57

Truth be told… This part isn’t very fun.

Slide 58

Slide 58

PIERCING THE SHADOW DOM This Photo by Unknown Author is licensed under CC BY-SA

Slide 59

Slide 59

What pierces the Shadow DOM? <custom-alert> <p>Light DOM goes here</p> </custom-alert>

Slide 60

Slide 60

What pierces the Shadow DOM? <custom-alert> <p>Light DOM goes here</p> <img src=”path/to/icon.svg”/> <slot></slot> <button>Close</button> </custom-alert>

Slide 61

Slide 61

What pierces the Shadow DOM? custom-alert button { background: pink; } button { color: pink; } custom-alert { —bg: red; —text: white; } Shadow Boundary body p { transform: rotate(-10deg); }

Slide 62

Slide 62

What pierces the Shadow DOM? custom-alert button { background: pink; } Shadow Boundary body p { transform: rotate(-10deg); } button { color: pink; } custom-alert { —bg: red; —text: white; }

Slide 63

Slide 63

A loss of control When you’re comfortable with the global, cascading nature of CSS it can be quite frustration when it quits working.

Slide 64

Slide 64

Slide 65

Slide 65

Styling Light DOM?

Slide 66

Slide 66

What about that <button>?

Slide 67

Slide 67

Deep Styling Shadow Elements?

Slide 68

Slide 68

But if this wasn’t difficult enough… Some styles DO bleed through the shadow boundary!

Slide 69

Slide 69

Inheritable Styles • • • • • • • • • • • • • border-collapse border-spacing caption-side color cursor direction empty-cells font-family font-size font-style font-variant font-weight font-size-adjust • • • • • • • • • • • • • font-stretch font letter-spacing line-height list-style-image list-style-position list-style-type list-style orphans quotes tab-size text-align text-align-last • • • • • • • • • • • text-decoration-color text-indent text-justify text-shadow text-transform visibility white-space widows word-break word-spacing word-wrap

Slide 70

Slide 70

Inheritable Styles • • • • • • • • • • • • • border-collapse border-spacing caption-side color cursor direction empty-cells font-family font-size font-style font-variant font-weight font-size-adjust • • • • • • • • • • • • • font-stretch font letter-spacing line-height list-style-image list-style-position list-style-type list-style orphans quotes tab-size text-align text-align-last • • • • • • • • • • • text-decoration-color text-indent text-justify text-shadow text-transform visibility white-space widows word-break word-spacing word-wrap

Slide 71

Slide 71

Inheritable Styles?

Slide 72

Slide 72

CSS Variables?

Slide 73

Slide 73

<two-up> styling API /* Two Up Styling API */ two-up { —accent-color: #777; —track-color: #777; —thumb-color: #777; —thumb-background: #fff; —thumb-size: 62px; —bar-size: 6px; —bar-touch-size: 30px; }

Slide 74

Slide 74

CSS Variables are a great way to add a styling API They offer the right amount of flexibility for most minor customizations.

Slide 75

Slide 75

More ways to offer styling APIs A few “hooks” to let their components be customized.

Slide 76

Slide 76

Custom themes or classes <custom-alert theme=”warn”> <p>Light DOM goes here</p> </custom-alert>

Slide 77

Slide 77

Slide 78

Slide 78

I’m still kinda mad About that button.

Slide 79

Slide 79

Named Shadow Parts <custom-alert> <p>Light DOM goes here</p> </custom-alert>

Slide 80

Slide 80

Named Shadow Parts <custom-alert> <p>Light DOM goes here</p> <img name=”icon” src=”icon.svg”/> <slot></slot> <button name=”button”>Close</button> </custom-alert>

Slide 81

Slide 81

Named Shadow Parts

Slide 82

Slide 82

Styling Light DOM Deep Styling Shadow DOM Inheritable Styles CSS Variables Theming Named Shadow Parts Shadow Boundary Crossing the Shadow Boundary

Slide 83

Slide 83

Crossing the Shadow Boundary Deep Styling Shadow DOM Shadow Boundary Styling Light DOM Inheritable Styles CSS Variables Theming Named Shadow Parts

Slide 84

Slide 84

Slide 85

Slide 85

Writing Web Components with JS

Slide 86

Slide 86

Web Component Lifecycle class CustomAlert extends HTMLElement { static get observedAttributes() { return [‘icon’, ‘theme’]; } constructor() { super(); } connectedCallback() {} disconnectedCallback() {} // componentDidMount // componentWillUnmount attributeChangedCallback(name, oldValue, newValue) {} } customElements.define(‘custom-alert’, CustomAlert);

Slide 87

Slide 87

Small libraries (5~10kb) exist to make writing Web Components nicer.

Slide 88

Slide 88

A basic example in lit ” <custom-alert icon=”note” theme=”warn”> <p>Alert message goes here.</p> </custom-alert>

Slide 89

Slide 89

A basic example import { LitElement, html, css } from ‘lit-element’ export class CustomAlert extends LitElement { static get styles() { return css` :host { background: var(—bg, #f0f0f0); color: var(—text); display: grid; gap: 0.5rem; grid-template-columns: 1fr 24px auto 1fr; align-items: start; padding: 1rem 0.5rem; } :host([hidden]) { display: none; } :host([theme=”danger”]) {

Slide 90

Slide 90

:host([theme=”danger”]) { —bg: red!important; —text: white!important; } :host([theme=”warn”]) { —bg: gold!important; —text: black!important; } svg { grid-column: 2 / 3; } button { grid-column: 4; grid-row: 1; justify-self: end; margin-right: 8px; } ::slotted(*) { grid-column: 3 / 4; margin: 0; max-width: 66ch; line-height: 1.6; } A basic example } `

Slide 91

Slide 91

static get properties() { return { icon: { type: String }, theme: { type: String }, } } A basic example constructor() { super() this.setAttribute(‘role’, ‘alert’) this.setAttribute(‘aria-live’, ‘polite’) } _close() { this.hidden = true; } render() { return html` <svg xmlns=”http://www.w3.org/2000/svg” style=”display: none;” > <symbol id=”note” viewBox=”0 0 24 24” fill=”none” stroke=”currentColor”> <path strokeLinecap=”round” strokeLinejoin=”round” strokeWidth=”2” d=”…” /> </symbol> <symbol id=”warn” viewBox=”0 0 24 24” fill=”none” stroke=”currentColor”>

Slide 92

Slide 92

} this.hidden = true; render() { return html<svg xmlns="http://www.w3.org/2000/svg" style="display: none;" > <symbol id="note" viewBox="0 0 24 24" fill="none" stroke="currentColor"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="..." /> </symbol> <symbol id="warn" viewBox="0 0 24 24" fill="none" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="…" /> </symbol> </svg> A basic example } } <svg part=”icon” height=”24” width=”24”><use href=”#${this.icon}”></use></svg> <slot></slot> <button part=”button” @click=”${this._close}”>Close</button> window.customElements.define(‘custom-alert’, CustomAlert)

Slide 93

Slide 93

A basic example

Slide 94

Slide 94

Slide 95

Slide 95

Slide 96

Slide 96

Slide 97

Slide 97

Slide 98

Slide 98

Slide 99

Slide 99

Slide 100

Slide 100

FAQ

Slide 101

Slide 101

IE11?

Slide 102

Slide 102

SEO?

Slide 103

Slide 103

A11y?

Slide 104

Slide 104

tl;dr • Custom Elements around form controls have some gotchas. • Getting better with ElementInternals and formdata • Focus management is tricky, like always. • inert may be a hero here.

Slide 105

Slide 105

What about my favorite things? • State management? • Server-side rendering? • Props? • Hot Module Replacement?

Slide 106

Slide 106

A few big ideas before we go…

Slide 107

Slide 107

Web Components build into the Web Platform

Slide 108

Slide 108

If we have good, accessible Custom Elements…

Slide 109

Slide 109

We have a pathway forward for more native elements <tabs>, <accordion>, <model>, <popup>, etc.

Slide 110

Slide 110

Slide 111

Slide 111

An easier Web lowers barriers Less complexity, less gatekeeping, a web for everyone.

Slide 112

Slide 112

Thanks Dave Rupert @davatron5000