Web Components:
Little Bits
Web Components are a way to enrich standard HTML with new behaviours by creating custom elements! Join me as I share my experience of developing complex design systems as well as custom open-source tools, all with the power of Web Components ✨
Videos
Links
- Zero Height
- Personal website
- MDN page on Web Components
- Zero Height post about web components
- MDN page on :playing pseudo-class
- MDN <audio> usage notes
- Random source web component codepen
- Breathing codepen by Michelle Barker
- Nord design system
- Provet Cloud
- Zero height Design Systems reports
- Slides from this talk
Transcript
Yeah, I'm Dave.
I work at Zero Height as a developer advocate.
We do design systems and tooling, and this is my dad.
David Daaaaarnes!
David Daaaaarnes!
David Daaaaarnes!
Good morning to you!
Well, sorry, it's a bit creepy at the end there.
So, yeah, this is my dad.
This is how he says hello to me every single time I pick up the phone or I call him or he leaves me an audio message on WhatsApp.
So any communication, it will start with him yelling my name down the phone.
So, it's a strange one, but so, yeah, so when life gives you lemons or life gives you a very loud dad, what do you do?
You exploit it for appetizing purposes.
So this is my website, darn.es, and there's a button at the top there, and when you tap on it, it makes a sound.
It's my dad pronouncing my name.
So I wanted to build this like a few months back or when I was rebuilding my website, and I thought, right, I'm going to go through with you folks how I went about building that piece by piece.
So let's start with it.
Let's beautiful an audio element.
How perfect.
It's great.
You press the button.
Whoa, that's loud.
Okay, I have no control.
Sorry, audio effects.
Maybe balance it.
But, yeah, it's semantic, it's accessible, it works, but audio elements are pretty annoying.
Like, you can't really like style it.
Well, you can, but you can't style it like cross browser elegantly.
Like, I can then comment this code up here.
Oh, no, we haven't got shortcuts.
We'll do it manually.
You try and style it, and you get that.
Like, you can fiddle around with it and try and make it work properly, but it's just not workable.
What you really want or what I want is this nice little button with an icon in it, and this access, I've always got the label and everything like that, but what I want is when you click on this, like, the audio to play.
So that is where Web Components comes in.
Here we go.
So what are Web Components?
I'm not gonna go through all the details of it because I think there's a lot of better people to talk about that.
Not only that, I've made a guide which I'll share in the next slide.
So they're actually a suite of different technologies allowing you to create reusable custom elements.
That's from the MDN docs.
So you have custom elements, HTML templates, shadow DOM, and dedicated CSS selectors.
You don't have to use all of these together.
Custom elements, you will pretty much have to use that in order to create the tag, the actual element.
Every custom element has to have a dash in it.
That's the only constraint for it.
That's the only main constraint for it.
The rest of them you can use totally optionally.
Like shadow DOM, HTML templates, and the CSS selectors are all these niceties on top to be able to use Web Components in a meaningful way on the Web.
I have water.
Great.
So, yeah.
Before I take a swig of this drink, I've made a little guide online.
If you go to this link, you can use this QR code or use the URL at the bottom.
I will definitely share the slides afterwards.
In fact, I already have.
This is on the Zero Height website.
If you sign up, you get this, and you can go through all the details about me making the case for Web Components.
It has a slight tilt on design systems because of my experience of using them in design systems as well as us being a design systems tool.
Okay.
So, let's turn on a Web Component live.
So, we've got here HTML on the left, Proovar on the right.
On the left, we've got the button element, and we've got the audio element.
I've wrapped it in a play button tag.
So, this is going to be our Web Component.
So, when I click on this, I haven't turned it on yet.
When you click on this, it should play the audio.
So, what I'm going to do is turn on or uncomment this script tag.
So, this is a Web Component I've made, and you folks can use this as well.
So, once that's enabled, you can then click on this.
I promise not to play it so many times.
It was quite annoying doing the slides.
So yeah, it works.
Click on the button, plays the audio, great.
But again, you've got the button, you've got the audio element.
We kind of want to make this a little bit more visually attractive, shall we say.
So, what we can do is utilize the CSS selectors I was talking about.
So, one of those is called, is a pseudo selector defined.
So, you can put play button colon defined, and that is a selector to be able to select the element when it is defined.
So, when that's defined, we'll hide the audio element, and then you'll see I've also put not defined.
So, that's a not selector.
That's like the exact opposite.
So, when that element is not defined, it's not being instantiated on the page, it'll hide the button, but it will keep the audio element.
So, it will just work like a normal audio element.
So, that's kind of, that's one of the great things about Web Components.
It just kind of falls back to a kind of gracious thing, especially when you put the markup of what originally it was meant to be inside of it.
So, it just kind of falls back to the basics.
Cool.
But, this button is cool and everything, but wouldn't it be nice if it kind of like shook a little bit or kind of responded to like show when the audio plays.
There is actually a pseudo selector called playing, but it only works in Safari, which is pretty annoying, especially when I started building it and you get so far and you go, "Oh, damn it.
It doesn't work in Firefox, it doesn't work in Chrome, or it's non-existent in all the other browsers."
It would be nice if it was in all of them.
But, oh well.
What we'll do is we'll use Web Components again, but this time as a polyfill.
So, we're going to polyfill for this selector using a Web Component.
So, again, here's our button.
I promise I won't click on it this time.
Well, I will in a minute, but.
So, again, the markup as before, the play button element, and we've got the button inside of it and the audio element as well.
But, this time I've got a is playing select--select--is playing tag.
So, that's going to be a new Web Component that is going to have a attribute added to it whenever any audio is playing inside of it.
And, in fact, this Web Component does that for video as well.
So, anything that's playing, it will add an attribute so then you can utilize that as a CSS selector.
So, I'm going to uncomment this.
There we go.
Oh, yes, and that's the play button like selector.
And then, we've got a is playing brackets using the attribute selector to select the SVG.
And then, I've got like a shake animation which is horrendously long down here to kind of create true variety.
And then, when you click the button.
Yeah, cute little shaky thing.
You could also use it to kind of like disable like interactivity.
Maybe you don't want people to be able to pause it midway through and stuff like that, but it's your preference.
So, yeah, now we're kind of building what I want.
This is great.
But, wouldn't it be nice if it played different audio on each click?
So, you hear my dad and then maybe you might hear something else as well at the same time or not the same time, one after the other.
So, like randomly go through different like audio things.
So, the audio element can accept the source element to be able to list out all the different audio files.
That actually is for like compatibility.
So, you've got your MPEG there, OGG and like MP3 and M4A and all that kind of stuff.
That's what it's meant for, but we could kind of like repurpose that and use that to list out all of the random audio things.
And standards people can slap me on the wrist later if you want to.
That's fine.
So, why don't we utilize that and kind of create that as a way to create like random like pool of audio to source from.
That's what I want to say.
So, again, here we are.
We've got our buttons and this time we've got a bunch of source elements in here.
So, there's still the audio element with the controls.
The button, we've got the play button custom element.
We've got the is playing custom element and then now we've got random source.
So, this is going to randomize through the sources.
Just for like logic, I prefer like the first audio to be the audio that's like semantically there.
So, the first one's going to play.
So, that will be my dad.
Sorry, you're going to have to hear that again.
And this is like going through my life, like talking to my dad.
So, now you all.
So, once I uncomment this, it's going to make that random source tag into like a proper web component.
And we'll click that.
Okay, that's one of them.
Come on.
Oh, you've got to guess who that is.
Does anyone know who that is?
Got it.
Nice.
You won't get that one.
That's my mother-in-law.
Oh, sorry.
All right, cool.
So, it goes through all random ones.
I think.
Oh, Mandy, please.
All right.
So, I'm kind of rushing through all these web components and I should stop and explain a little bit more like contextually about this stuff.
So, what I'm going to do is I'm going to live code.
I've been uncommenting stuff and it seems to be working.
So, I'm going to do a live code thing.
So, the next thing I want to do is I want my name next to the button.
And my name to kind of animate in this same way, this cool demo by Michelle, to animate the letters as it goes along.
So, when my dad says my name, it kind of goes through all the letters and animates kind of elegantly and it should do that for every audio play after that.
So, yeah, it's time to learn tech.
Damn, this is going to be bold.
But it's working.
It's working so far.
So, for the purposes of this demo, I'm just going to stick to the audio element just on its own.
Again, that's the cool thing about web components is that you just wrap it around the right kind of semantic elements that you need in there and it's just going to work as expected.
Especially when you make them really kind of small, like little bits.
So, what I've got is a audio element and then that's wrapped in this new web component called duration property.
So, that's going to have a style attribute on it and a duration custom CSS property.
So, like a variable that we can store and claim and use inside of our CSS.
So, that's going to have the duration of the audio from start to finish.
And we can use that for the animation duration.
And then I wrapped it in an is playing component just so we can style it to see that it works.
Because it needs to I'm going to show the number, but I need to see it kind of play from start to finish so it goes in sync with like the audio playing.
So, it will kind of scrub along with this, I guess.
All right.
So, yeah, I've got some styles in there to show, like, that it's actually going to work and stuff.
So, first thing to do is web component is to instantiate it.
So, like, put it in there.
So, it's there to actually use.
So, we're going to register it.
So, this is just a registry thing.
It's just going to tell it this is a component.
This exists on the page.
And that red border means it's there.
It's defined.
It's actually in the page.
Or present.
So, the next thing we want to do is we want to get the player.
We want to I'm just going to have a bit of water.
Yeah.
So, the next thing we want to do is get the audio element that's inside the component.
So, we can do that with the get.
So, that get there.
Or let me know if this is too small.
Is it okay?
Thumbs up at the back.
Cool beans.
So, this is just query selector.
Just grabbing the audio or the video element if there was one there.
And that's going to grab that and put that as, like, this.player, which is inside the web component.
So, any time we say this.player, we can grab the player that's there.
The next thing we want to do is I'm going to add a set.
A setter.
So, this will set the duration.
So, it will set it as a custom property.
So, it will just put it on there as a style on the actual, like, web component itself rather than the audio element, like, directly.
That means that we can leverage that, like, outside of the audio element.
So, anything inside can kind of use that selector and you can kind of nest in and style stuff.
And then the final thing we're going to do is going to use connected call back inside of a web component to actually apply that.
So, you'll see underneath the audio element, I'm using a pseudo element there to kind of display it.
So, that 3.6652 blah, blah, blah, blah, is the exact duration of the audio.
So, that will apply it.
And it will listen using duration change.
So, any time the duration changes, that means any time the audio is changed, it will update this.
So, that's kind of the best way to do it.
Because that gets, like, called like when the audio is actually inserted in.
So, it will work first time and it will work subsequent times when the audio gets changed through the randomization.
So, let's test.
Perfect.
Cool.
Wow.
A demo live.
Success.
Cool.
Okay.
So, now we've got that's a web component.
We just made a web component together.
Don't worry.
You uncommented it.
It's just like copy from Stack Overflow.
All righty.
So, to return back to the context of our little play button and the animating text.
So, what I've done here is I've split out my name into, like, span elements.
And then I'm using a custom property again to kind of mark each element in the index.
That's what this is this whole, like, stream of garbage here is each span element wrapping each letter of my name.
And then you'll see I equals zero or I equals one, I equals two, and it just goes through it and that.
So, you can utilize you can understand the order of those elements in the string and then animate them using the animation duration that we've got.
So, make sure all the code's uncommented.
So, when we click this.
And it is random.
David.
Darnes.
David.
Darnes.
Oh, who's that one?
Damn.
That's Rob Knight.
That's Rob Knight.
That one's obviously Untitled Goose.
So, yeah.
So now that will animate perfectly to, like, in timing with the audio that's, like, played.
I'm really scared about clicking it again because I'm worried it's going to my dad again.
So let's move along.
David.
Darnes.
It's like a gamble, isn't it?
All right.
How are we doing for time?
Dave, are we good for time?
He's just checking his emails.
It's fine.
Are we good for time?
Yes.
How long have you got left?
I've got a couple of minutes.
Fantastic.
Cool.
Cool.
I completely lost track of time.
What I'm just going to explain is about, like, the scale at which Web Components can be used.
Because I've been showing them at a very small scale, like, little bits.
Hence the talk title.
But prior to working at zero height, I worked on Nord design system.
And Nord design system is a design system for Nord health.
It's for all sorts of healthcare products.
That's both for people and for pets.
So yeah.
And the -- all the components were built using Web Components.
From the ground up, I mean, we did use lit as a library to help us get there.
But everything was built with a Web Component.
Or Web Components.
And that was for compatibility and versatility.
Being able to use it inside a framework, outside a framework, in any framework.
Asterix used the latest version React, if you have to.
But yeah.
Sorry.
So as you can imagine, a lot of components, a lot of stuff that's all being, like, supplied as a Web Component.
And this is one of our -- or one of the projects that I worked on.
This is called Proveit Cloud.
This is for veterinarians.
An application that does everything inside of a veterinarian place.
So they do all their finance and their appointments and their bookings and everything.
And this is all Web Components.
And this I find really cool.
So you see there's two windows, like both of them resizing.
So that's a Web Component to, like, send that information using I think it was local storage or Cessna storage to pass that between them.
But the catch here is this is a Nuxt application in this window, which hadn't been released.
And the window on the left is a 10-year-old Django application.
Like over 10 years old.
And they both use Web Components.
They both use the identical components.
And the implementation of the Django application with Web Components was weeks, we're talking about, to put Web Components in it from, like, markup that was a decade or more old.
So I find that this is, like, really powerful, like, example of using Web Components.
The versatility and how forgiving they are when you drop them into, like, any sort of markup.
Anyway.
Right.
To wrap up, if you want to get in touch, you can do.
You can use this link here.
There is actually a little, like, Easter egg.
If you want to upload an audio file and maybe do your best impression of my dad, then you are welcome to.
There is a little thing in the form where you can upload a file.
So.
Yeah.
And finally, I need to let people know because there wasn't cards for everybody on all the seats.
But at zero height we are doing a design system survey.
We do it every year.
We have been doing it for the last three or so years.
We want to hear from you folks that are using design systems.
Using them, building them, especially if you're a developer, we want to hear from you.
We want to know how we can help.
And not only that, we want to share with the community how you're building design systems because it will be really valuable to the community.
So, yeah.
But if you need that info, happy to share it afterwards, like, or during lunch or something like that.
I just realised I'm holding you up from all your lunch.
What are you talking about?
Thank you very much.
[Applause]
About David Darnes
Prior to being a Developer Advocate at Zeroheight Dave has been providing his skills in front-end development, design and technical writing to companies such as Zeroheight, Nordhealth, Google, Buffer, Netlify, Ghost, Octopus Energy, Stackbit and many more.