Learn With Jason Live, LIVE! The CSS-stravaganza!
with Adam Argyle
Adam Argyle likes CSS. In this episode, he’s live in studio teaching us about everything from @property to @layer to scroll-snap and a whole lot more.
Topics
Resources & Links
- https://nerdy.dev/
- https://developer.mozilla.org/en-US/docs/Web/CSS/@property
- https://open-props.style/
- https://www.learnwithjason.dev/build-custom-interfaces-using-css-open-props/
- https://gradient.style/
- https://mdn.io/audiocontext
- https://kit.svelte.dev/
- https://github.com/learnwithjason/noisee/tree/main
- https://developer.mozilla.org/en-US/docs/Web/CSS/system-color
- https://twitter.com/argyleink/
- https://thecsspodcast.libsyn.com/
- https://nerdy.dev/introducing-the-bad-at-css-podcast
- https://developer.chrome.com/blog
- https://www.youtube.com/live/tSfSY3Ni3X0?si=3e7bYhuTrAOCQOI8
Transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
Some captions were not present in this episode, due to audio issues and have been attempted to be recovered.
JASON: Hello everyone welcome to another episode of learn with Jason, today on the show we are live in studio with the one and only Adam Argyle, how you doing?
ADAM: Hello, I'm doing well, I'm Happy.
JASON: I'm so happy to have you here, this is gonna be a lot of fun this is the the second attempt at doing an in-person show but it's the first one where we've got multicam, so this is gonna be a lot of fun we are gonna be able to to focus on everybody as we go and we're gonna test my multitasking skills as I attempt to have a reasonable conversation with Adam monitor the chat build an app and also control the cameras.
ADAM: You got this I've seen you do worse. [Laughter]
JASON: So Adam for folks who aren't familiar with you and your work do you want to give us a bit of a background about who you are what you do.
ADAM: sure engineer focus heavily on CSS front-end UI I want things to feel smooth and look good feel good it's like you get in a car and one is crusty and one feels nice and you're like no I prefer the one with the nice interior right that like form fits to you as you sit in that's how I like websites I like to think about them in that way that you open it up and it just goes I see you and it form fits to fit you rather it's your color scheme or whatever, anyway I just love animated good interfaces probably because I love video games you know something around there and now I work at Google I've been in the industry for 20 years building websites and I focus on CSS on the Chrome team trying to make it easy for you too.
JASON: I love that I I mean I've been following your work for a while I feel like we've been friends for a while and you have this knack for building like very simplified use cases that are just so nice to use and I I find that to be so like pleasant to work with right you some of the more recent ones we can look at a few actually as we switch over into screen sharing but like you did some things with just you know like a squishy image carousel and like you know things that just they just kind of like you use it you go [satisfied guesture] [Laughter]
ADAM: that is the feeling I would like to invoke yeah and I feel like I'm a sushi chef in the middle of a bunch of other folks that are like cooking in big kitchens with big you know like if you're in a corporate cooking situation right you're gonna have all these chefs all this process and I'm in the corner making sushi trying to bring as much joy to you with this smallest amount of ingredients as possible.
JASON: I love that I mean and I do think like it it's very interesting to me the it seems like we've we've almost gotten to a point where CSS itself doesn't get taken very seriously I think as a as a general rule which is really a bummer because CSS has so much to offer and is especially over the last couple of years just like so much more powerful than than anything that I would have imagined you know 20 years ago when it first came out or I mean not even not even 20 years ago right like it was late 90s no wait when did it come out I think it's 30 years old or something like that
ADAM: is it full 30 yeah
JASON: oh my goodness
ADAM: there's some early early CSS in there but yeah it's old
JASON: yeah so so you know back in the early days when it was like everything was afloat everything was uh you know you didn't have a lot of these custom layout things but then fast forward today we've got grid we've got animation we've got uh we've got cool color spaces we've got like variables we've got control flow we've got feature detection like it's starting to feel a whole lot more like a real programming language um and and what I've noticed is that folks like yourself have started pulling together um like just what sort of feels like uh I this word has a load it's like loaded but like artisanal movement of like people building stuff that feels really good um and and what I love is seeing the stuff that feels really good um and and what I love is seeing the stuff that feels really good stuff that you're putting out you know the the rest of the folks on your team you know like Bramus like doing amazing stuff um but also folks like you know Lynn Fisher is out there doing incredible stuff with CSS and uh you know I'm I'm like blanking on additional names but there's so many people doing so many cool things to highlight what you can do with just CSS I even saw somebody who'd written like a it was a Morse code interpreter that was pure CSS I tried to look at the I couldn't understand the code at all because it's very like esoteric but it's cool that that's possible so um I guess what got you into like how did you become a CSS specialist
ADAM: okay so I was in school uh learning Java uh studying SQL PHP um kind of anyways
JASON: that was before they added the script to it right
ADAM: before they added the script to
JASON: to the Java
ADAM: ah, JavaScript was out but it just was it was a toy language which is still how a lot of people treat JavaScript they're like JavaScript is the Yolo version you gotta write TypeScript if you want to be hardcore anyway okay so I'm in class right and all these people are building their assignments and they're happy to just print uh the calculation to the console you know and that was them feeling finished with their work and I've been playing video games like my whole life I love them and I'm like you're done but there's you can do more and like why don't you make it look good why don't you make it do something cool and animated and there was all these opportunities and so I kept extending myself beyond the basic assignments and doing something that looked good I was also struggling so hard, I was not a natural coder, everyone else in the class seemed to be very very good at it right away um and so I had to work really hard just to get my console log to print and then I would go the extra mile boosting up all the animations and so once I was in classes long enough to realize that I was one of the few that cared about how it looked in my in my school I switched so I finished my um it was like an AA in computer what was it called database and web scripting it's like database admin and web scripting or something like that anyway I switched to art school and then I got a job in the field so I focused on the art side I was like if I'm if I'm interested in it and none of the other developers are I should go focus on that a little bit and that kind of began my journey of what quickly became fulfilling uh designer's dreams I was like I make designer's dreams come true.
JASON: I make designer's dreams come true is that was like the first business card right it like you forgot to put your name on it you were so excited about that [laughter]
ADAM: yeah and I just so yeah I've been loving it since then since I realized I was the weirdo that could that cared and yeah
JASON: no I think that's I mean I I find that to be really exciting because it's you know I talk a lot about being a generalist and how I tend to dabble in everything and and never really go deep and and so it's always really fun to talk to somebody who has has sort of taken a specialist approach and like you know let's get down to the bottom of this and see what's really possible and like how can we take this as far as it can go because it you know it just the stuff that you come up with doesn't even occur to me as being possible right and then you're coming out and then of course I'm going to just copy paste it because now I can do that like hey great thank you for giving me this toolkit so that I don't have to learn how that works.
ADAM: you are welcome I love it that's like the best part about it is that this stuff is forkable takeable right um it's a it's a huge feature of our industry.
JASON: I agree I think I mean you know we give each other crap for for copy paste but I think that it really shows that you can you can basically level up in a day by finding a good example and then being able to you know you have to know enough to reverse engineer it because you can't just like copy paste it straight up but like being able to say okay you did this and if I take this and I change these little bits I've made something that's unique to my thing but I didn't have to learn like the underlying like here's how to interpolate values in CSS or something like that right yeah so speaking today so what do you have in mind.
ADAM: I have built uh an ephemeral noise experiment uh but it's like silent noise where we'll share a visual art experience that we can't hear each other but we can see the sounds that we're making
JASON: which I guess we're gonna that will be mostly true because, like in in normal practice yes today because you're gonna see us making the noise and also uh and also see the the output of it you'll be able to hear the sounds we're making that that put the thing on but usually no
ADAM: usually we'll be able to see your viewers noise
JASON: that's true yeah this is gonna be this is gonna be team play y'all so uh so be ready when we get to the right point it'll be you know probably about two-thirds of the way through the episode we're gonna ask you to open up your browser and turn on your mic and make some noise and that can be yelling waving your arms plug in your guitar do whatever you want right uh we're gonna we're gonna try to have a lot of fun with this so do we need to cover anything else before we just start looking at code I want to make sure we have enough time.
ADAM: let's jump into some code
JASON: let's jump into some code all right so so let's do this let's go to let's go to group mode where you can see look he's real I can I can touch him I can push him um okay we're here together
ADAM: I can see the bunny I was like I should have brought a big mustache and put myself there on the wall.
okay so let's let's get the the code up on the window I've lost my screen. We're just gonna fix that real quick. There we go. And all right we are talking to Adam Argyle. So here is a link to the site. That is absolutely not the thing that I was trying to view. There it is And then we've got How are y'all doing? It's good to see you. Ready to make some noise We are but not just the regular live where it's on a Zoom call but like the live live So happy about it. Synesthesia but make it CSS. I mean Ooh That's kind of fun. That's kind of fun. Me holding back my laughs. I would never hold back a laugh. That's... It's like holding back a sneeze. CSS podcast with Una. That is a fantastic thing.
ADAM: Thank you
JASON: Everyone knows Adam, We don't want ever to rob anyone of the chance to talk about what they're into. Okay First time you;ve joined a linkedIn live Oh, hi Sarah How are you doing? Okay So we have You gave me a doc but im going to do my best to only look at it when I need a link so I'll let you drive. So what do we wanna do first?
ADAM: All right So I kind of want to build folks up to how I came up with the idea. If you've followed me on Twitter, I love gradients and I like brutalist design and architecture and so I also wanted to build something with Party Kit. This was my own volition. I just like real-time experience. Sockets are cool yall.
JASON: Sockets are cool!!.
ADAM: Sockets are cool. I feel like they're not used enough.
JASON: I 100% agree. I think they were used enough for how hard they used to be to use. But I think that now that we've got tools like Party Kit they are definitely not used enough.
ADAM: Yeah I built a social network where everything was so real-time. If you changed your avatar it pushed the avatar change to everyone there. So imagine you're scrolling your feed and someone changes their avatar and it changes in front of you.
JASON: like that.
ADAM: Anyway So we'll look at a simple app property animation because app property is this unlocking potential for different types of if you wanna interpolate a variable app property makes it quite easy. And that's because you tell the browser a type and then it can know when you're going from one value to the next that it should stay within the type. So anyone that doesn't know CSS has types They're enforced types through @ property. And so our first demo is gonna just show you how to do a basic app property interpolation. We'll set one up and when the slider changes values it'll write a new value to the custom property and the custom property will interplay from where it was. So it's a basic transition of a custom property.
JASON: Sick Let's do it. All right We're looking at the @ property syntax here on MDN. I dropped a link into the chat for that. Let me put that up on screen for a hot second. Also can I show you a trick that has really made my life easier? Watch this.
mdn.io/@property Gasp. And it shows up on this page. Wonderful work by the MDN team.
Okay I'm going to create a pen.
ADAM: I have one prepared. JASON: You have one prepared. Then I'm going to go into the doc and I'm going to click this one.
JASON: I was noticing, show everyone here your knuckles
do you see the curly boys, the square boys and the round boys on the knuckles I will fully be stealing that idea.
Adam Awesome.
JASON: I hope that you're ready because I've been thinking about knuckle tattoos and what I was going to do is I was going to get snug life across the knuckles which I thought was really funny. But I don't know I think the Curly boys. Symbols are fun.
ADAM: They're my favorite tattoos on my hands. Oh man They're very exciting. They felt like a prison thing you got. You're like
JASON: I'm tough. [Laughter]
ADAM: I'm tough now, but I got super nerdy ones, I got earth wind, water fire and then the four elements of coding. So I have like the four elements of earth and the four elements of coding and they're coming for your face. I don't know. Need a more clever new thing.
JASON: Oh geeze It's so good. It's so good. Yeah. Oh Okay. People are into the tattoos. This is good. All right.
ADAM: I have so many nerdy ones. I got like webs and spiders
JASON: I got a lot of tattoos when I was in a band and then I got into being what I guess is an adult and it just like I've been very slow to get more tattoos.
From CSS to MMA. [Laughter]
All right So we're looking at, I see an H1 and then we've got a range slider
ADAM: Notice the ID is demo and then the ID of the input is size And look at the Javascript. It says size.onInput. JASON: Wait.
ADAM: I'm sure most of your watchers have no idea that that works JASON: since when
ADAM: forever that shit is old as time man, IDs are on the window object they're unique and they're always available with no selector no query selector you've given something an ID you can just reference it because it's it's there.
JASON: do you ever have one of those moments where you realize how many minutes of your life you've wasted, me typing document dot query selector is is one of those things.
ADAM: I I love the API I hate typing that out, I even have a library called bling bling js, it's an es6 module.
JASON: does it just make it into the jQuery...
ADAM: it's the dollar yeah and it just makes it and I'm like this script alone will save you characters it's a really tiny important.
JASON: this was this was yeah look at this look at look at this we've broken we've broken the chat [Laughing] yeah people
ADAM: yeah look at the code size on input and then demo dot style, yeah frameworks are great they make this stuff easy I'm like there's nothing there so again I'd like the sushi chef style right I'm like how much can I shave off I want you to get the to get the thing done.
JASON: the good good, all right so uh okay so we're looking at the size dot on input, okay I'm gonna get over my my rage um and then inside of this, I'm just gonna make this even bigger, inside of this, we're taking the demo, we're setting the property to and then we're setting a size uh variable and that is going to be set to the current range value which is somewhere between zero and 300.
okay okay i'm in, i'm following that and then in here we've got, we're importing open props okay
ADAM: just the easings because there's some sweet springy bounces in there that just bring some life
JASON: and for anybody who's not familiar with open props that is a collection of css variables that you maintain that is compatible with everything right like you can use it with plain css you can use a tailwind you can use it with kind of whatever you want right.
ADAM: yep they come in javascript the flavors they come in css flavors there's json tokens so that you can integrate it with cicd it's trying to collect the world's most impressive uh things that you can put inside of a variable all in one place and so some of it feels like a design system and some of it is just for funsies and some of it is mad rad tricks holy crap the masks you and the gradients you can tuck some incredibly strong features into just a well-named variable and so that's kind of what it's doing it's trying to be that that aggregator.
JASON: it's real good stuff uh we have an episode up about it on learn with jason so if you head over to learn with jason and you type in open props you're gonna find this episode here.
ADAM: yeah i remember
JASON: i hope you do yeah you were there
ADAM: i was there, yeah we built the next site
we did build a next site, why did we build a next site, like of all the things.
ADAM: i don't know it's easy to spin up something that had some data and some stuff to style.
JASON: yeah never done this with css about to start exploring crawling out of the back end all right welcome welcome to the front side.
yes this is this is wonderful all right so um let's let's climb on in uh css variables are one of the the best recent css things i agree um it's and it's fairly recent like like the last five years or so.
ADAM: they feel new i feel that's kind of why open props feels innovative is because um they're new enough that we're still learning what they can do and what you can tuck into them i mean people have put sql queries in css variables before just let that sit a second and javascript you can put javascript in the custom property.
JASON: and that that i have done um that's actually really useful because you can you can kind of like well it's sort of what you're doing here like we're telling we need a little bit of javascript to react to somebody's input but by putting most of it into the css we just kind of let the css do the thing that it does um and then we have access to whatever's in the css property which i guess like if you need a javascript you could also put that in the data set or something and maybe not need a css variable but hey whatever use the tools you got right
so all right let's take a look at this so we've got um this @ property and immediately this looks a little different than like what you might expect if we were doing uh the way that i'm used to which is to do something like this yeah so why don't i write it like this like why the why the extra
ADAM: so when css since css is so loosey-goosey about what you can put in a custom property it doesn't do any type information like you're doing for instance like javascript does right javascript you set var or const to something and it goes notice that's a string and it kind of dynamically types it for you uh this is the nature of it dynamically.
JASON: this is this is what uh javascript sounds like in your head.
ADAM: notice you're trying to do a loop bro [laugher] ADAM**: p**ersonified scripting i love it.
So javascript can do that, css with customer property, it intentionally is naive and so we have to be like explicitly tell it this size is a length so notice the type there it's kind of kind of kind of got an xml shape to it, you give it an initial value which needs to be of the same type or else obviously it won't work.
JASON: things will explode yes.
ADAM: and inherit true means that this thing will bubble down so you can basically have an @ property that feels a little bit like a const that's at the root and can't be inherited and then you can make these ones that do get changed and trickle down in the cascade so.
JASON: So if you set it to true it can be changed if you set it to false it wouldn't update if you tried to update it.
ADAM: it wouldn't update on children but it itself would update.
JASON: oh i got you i got you so, so then uh you would have to update the child element itself if you wanted to
ADAM: it gets weird i think it just doesn't change, it doesn't cascade so it also means you can get perf benefits from it so if you set inherit to false and you register all your custom properties that way they're naturally a little bit faster because it doesn't have to worry about the tree, it just worries about the root
JASON: so here's a bit of a nerd question, when css is doing this is it offloading to the gpu or is it doing this on the cpu
ADAM: currently custom property transitions and interpolations are on the main thread they are on the cpu, they are not gpu accelerated to my dismay and bramus we're constantly like we're like we've got a bat like a homie the clown we're over there with the devs like we want gpu accelerating custom properties, anyway i don't know how many people know homie the clown but it's probably dated me pretty quick.
JASON: homie the clown that was that's old snl right like that's like damon wayans yeah oh man back in the day uh just.
JASON: okay so let's actually look at the css so we we've got our custom property yep and then in here you set up a layer which what
ADAM: okay cascade layers uh normally in css until we got cascade layers everything you wrote was in one layer and so if you've been using tailwind for a while you notice the tailwind has had layers in sass and that allowed you to sort of ahead of time articulate the the stack like almost like a bunch of pancakes for your own css and this was nice because you could dynamically and asynchronously put something into a layer later so normally before we had layers before post css had layers you always had the index.style file that was uh very meticulously hand managed in order right you're like yes if you move bootstrap down one line all hell breaks loose you know.
JASON: that's i mean i think that sort of thing is where this idea of like the append only css file comes from is that people learned that like order mattered so if you were going to change something you just put it at the bottom right you didn't change anything else because you might break the cascade yeah um which is yeah i like i think is a legitimate challenge with css and i i definitely understand why people have looked for so many so many different solutions to get away from the cascade so this is a native solution.
ADAM: yep every browser has this it went interop, uh baseline across all the browsers last year all at the same time it's like one of those amazing things where it just sort of landed um and what it allows you to do is is create your own sections and then just put stuff in it at your own will at your own rate at your own speed it could be after the page loaded so imagine you've got a reset dot style sheet and you you know you need to have that at the top so that everything else can overwrite it so imagine you could load that 10 seconds later in the page and stick it on top even though everything else is already loaded and you just told it to go into the layer of reset and so it allows you to any time whether it's at your build time most people do this at build time but you can send it to the browser like if you go to my site nerdy.dev you'll see a bunch of cascade layers and they're i like them because they do a few things first off they give me this ordering that i don't have to be so meticulous about it b it leaves a breadcrumb behind about the intent of the import so when you import a bunch of stuff usually you're importing a normalize and a reset and then you're importing some sort of third-party libraries and then you're importing your own base layers and your own custom properties your own design tokens and then you're doing you've got all these things and you probably were writing comments for it but if you look in the styles pane of my website it's in the layers it'll say uh at layer you know normalize at layer design system at layer components and so all of my components go to components.dialog components.card um and it so you get to articulate kind of what the intent was you get the benefit of not managing it and it just starts to feel very ordinary and i think people like organization it's almost like es modules you're getting to pull things out into smaller chunks and worry less about the cascade but still be in full control it's pretty rad.
JASON: so a question on this is how do you define the ordering of layers because when we're looking here we've got like layer demo layer demo dot support are these in order like if we swapped these back and forth would that change the way that that things worked.
ADAM: so the way that i did it here is a very uh it's like as they are getting discovered which is a lazy way of doing it the way that you'll probably do it in your application is at the top of your first file that gets loaded you establish the the stack.
JASON: and what that means is um if i remember correctly we can put something right up here, @ layer and then we would do like demo demo dot support and that specifies the order and then if i want precedence to change i can just take this and move it here.
ADAM: sort of except that support is a is inside of so you can have layers inside of layers so demo.support is a layer inside of demo as soon as the browser sees demo.support it creates the demo layer for you and a layer inside of demo called support so usually what someone will do is they'll be like at layer reset comma normalize comma or whatever and they'll establish the whole thing there and then they'll put components and then at the very end is overrides and this is like a really really powerful thing also is that overrides one since it comes last you don't have to put at important on anything i i think that people don't realize a lot about uh cascade layers is they severely reduce the specificity of your selectors you don't have to battle something else because if your layer comes after another one it's like a whole new style sheet cascade document is available for you.
JASON: and so this this is sort of the same thing that we get when when people talk about why they like tailwind why they talk about uh css modules why they like uh stylex or css and javascript and stuff like that js is that when you when you identify this layer you're basically saying like for the thing that i'm targeting in this layer you can ignore all the other styles like this takes precedence and so it doesn't remove the problems like i know in the in the shadow dom for example you wouldn't inherit like root font styles so you'll still get those but like you're not worrying about something in a component that scope to that component layer isn't going to interfere with the css for this other component layer uh so theoretically like you can build your whole design system with tightly scoped everything with no css pre-processor because of cascade layers.
ADAM: yep two really cool use cases let's say you import a tailwind or bootstrap bootstrap was a notorious one that you had to battle right you're like i have to learn specificity in the scoring just so i can defeat the score of this selector well if you import bootstrap into a layer and then you have another layer that comes with more importance you can just do button and your selector will win over the bootstrap button even if the bootstrap one had important on it all you have to do is simple select and change the style and the browser looks at your layers and articulates them and applies them it's really really cool.
JASON: This speaks to my heart as somebody who is is very interested in kind of peeling back the abstractions and and re-examining like what does the browser just give us right because i feel like i learned a lot of ways to compensate for things that weren't implimented into the browser yet, when i was early in my career. If I never stopped to look at whats being added to the platform, I might just think, like, maybe you always need jQuery or Tailwind or whatever the thing is. But the platform is evolving, these days, it feels like at the same rate as the framework systems. So as fast as frameworks are coming up with new solutions for things, once the community seems to standardize on one of these solutions, we're getting to see the platforms implement a way to do that doesn't require any additional framework, doesn't require any extra JavaScript, extra CSS, extra anything. But we have to take the time to look. We have to take the time to look, explore, and see what is the platform giving us that maybe we don't need to reach for this tool or that tool anymore because those tools blaze the path. I think it's important whenever I start talking about this stuff because it sounds like I don't like tools. I love tools. But the goal of any tool that's supplementing the browser functionality should be to eventually become obsolete.
ADAM: I agree, yeah.
JASON: And that was what jQuery was very clear on. Our goal is eventually to not need to exist. I thought that was so dang cool that when, you know, query selector and some of the other pieces that were really popularized by jQuery maybe their way into browser standards, you stopped hearing them say you need us. It was like if what you're doing is doing basic selectors, just use the platform. That didn't prevent jQuery from being in 70% of websites today. It's very, very popular, and for good reason. It was an incredible library when it first came out, and it remains a great utility library. But that's a good thing. We should celebrate when a tool is no longer necessary. It basically changed everybody's mind about how the web should work. Now that tool can say, like, we did it, y'all. Now we can chill.
ADAM: SaaS has paved tons of paths. Just like jQuery did, it was supplementing features that people needed. It had layers first. Well, it had variables first, but now we got a more realtime custom property that was more powerful. You had these opportunities when it goes into the platform to even add a little more. Put it closer to the middle and really lean into the features. So SaaS had nesting, still has nesting. Color spaces, layers, all these features that so many of them have made it into the browser in the past five years or so that you don't need a build step. I still use a build step for concatenating my files. I've got a bunch of imports and stuff, and I like it when that happens. Astro will do that for you too. There's a couple other small things I like. So I'm very much these days using a pre-processor for couple of nice to haves. But if you check my website, I'm using native nesting, native cascade layers. I'm shipping that stuff to the browser. Don't visit me from IE11. That's not good.
JASON: I love that. For a personal site, you can safely make the choice I'm building for the modern standard. I'm not shipping things that only work in nightlies of WebKit or something. But I'm definitely using stuff that isn't going to work if you're on even two versions back of Chrome or Firefox. I like the idea of let's get this stuff out there. Let's see it in action. Let's normalize the use of it so that the platform sees that if they give us these tools, they're going to get a lot of action. I feel like I'm not the only developer, and judging by what the chat is saying here, I think there are dozens of us who are very, very, very excited about this idea of being able to leverage the platform for as much as possible or even all of it. I cannot wait for the day that I just build a website and I don't need to worry about Vite anymore. And Vite is great. You don't even have to think about it. But it would be cool if I didn't even have to install it. And we're getting closer to that every day. What we do to use Vite is so stripped down compared to what we used to need.
ADAM: Module resolution, concatenation. There's a few things. Live reload. But if you open up workspaces in the dev tools and edit your code directly, you get live reload. In fact, it's faster than live reload could ever be because it's direct manipulation. The list goes on. But yeah, I'm still a big fan of Vite.
JASON: And again, these tools, we celebrate these tools because they're doing incredible things. Then we look forward to the browser learning from what these tools are doing and adopting the best ideas and making it so that we don't need to install another tool. We as web devs just have the tools. Even dev tools is a great example. Back in the day, dev tools was an add-on to Firefox. The browser saw that actually that's a great idea. That should just exist. Now none of us have to go install Firebug or tweak our settings or get a bunch of user scripts and extensions. We just get this powerful stuff in our dev tools that just works. We don't have to know that it's there, other than to open it. We don't have to go seek in the community which tool does the right thing for my browser. We just have it, right. And so I'm very, very excited to see the way that this -- this trend makes me very happy. Okay. Can we get through the first demo here?
ADAM: So one of the reasons I like to use cascade layers in a demo is it's very clear what you should be studying if you like the effect. The rest of it is support. So this would be so common. You'd open up a CodePen and there's be like 50 new lines and then a bunch of styles tucked at the bottom. Like, oh, don't look at these. Or you'd have to scroll to the bottom of the file to see what's doing the cool trick. So I like this because I get to use layers. Layers mean the order doesn't matter. I get to promote the stuff inside of demo more than the stuff in the nested layer. So the nested layer is there, literally supporting the demo.
JASON: And from a practical standpoint, this has nothing to do with what we're demonstrating. This is just to make things look kind of nice. So we can really collapse that, and let's look here. This is what's actually happening.
ADAM: Yep, and I think that's nice as you're learning and trying to study. The focus is really clear. The noise -- right, this is noise to signal ratio. Signal is really clear if it's clearly labeled.
JASON: Okay. So let's talk -- I'm going to take this out because that isn't actually real. That was just me demonstrating the syntax.
ADAM: This is fun. I'm having a good time, Jason.
JASON: I know. It's so much -- okay. I love doing the show remotely. I will never not have a guest on remotely, if that's the way it works. But if we can get in studio, every time.
ADAM: You can cut the vibe with a knife in here, y'all.
JASON: It's so good. We can high five when something is good.
ADAM: So nice!
JASON: Oh, human connection. (Laughter). I apologize. Got a little excited. So we have two lines of CSS. This came out of open props. This is a variable that just gives us the ability to not have to know how the math for a spring works. Great.
ADAM: And if you look at the value of that, it'll blow your mind. It looks like binary code. I didn't write it. But I defined it. Anyway, now it's easy for you.
JASON: So then we've got use cases. Here's our size property. I'm going to do my best to understand how this works, but I already know that I don't. So the transition part, I get. We can set the transition. We're saying we want to transition the value of size when it changes for one second using the spring. Got that. So for the box shadow, it's zero offset, zero X and Y, zero feathering.
ADAM: Zero blur.
JASON: Then we want the offset as the size. What the heck is this?
ADAM: There's a lot of system colors. That's a system color. That's literally the highlight color you set in your system.
JASON: What?
ADAM: There's also one called highlight text, which is the text color that's appropriately going to contrast against a highlight background.
JASON: What?
ADAM: Yeah, there's a bunch of them. There's canvas, canvas text. I use them all the time because you basically get a free light and dark mode. These also play nicely with the color scheme property you saw on the HTML route in the support.
JASON: So --
ADAM: There's the blue as you highlight text.
JASON: Okay. Then we go back to dark mode. I'm literally just toggling my -- where is my -- oh, I can't because I'm in full screen. I'm in my system settings right now toggling my setup. Okay. So we're going to leave that in dark mode for now. So what I could do is I could make that red. Okay. I had no idea that was a thing. That's very, very cool. And super helpful. So many times I'm trying to guess what that color is and approximate it, knowing I could just pull it -- again, how many hours have I wasted? So this is cool. We've got two related lines of CSS and a five-line property definition, and we've got this really cool thing that we're able to do where we're interpolating values. If we take this and do the root size zero, it can't do the animation.
ADAM: The browser goes, oh, zero pixels to 20 pixels? I don't know what you mean. To me, they're just strings. You're like, you dork, they're not just strings. They're pixels. They got a PX on the end.
JASON: You silly. (Laughter)
ADAM: And yeah, you got to hold its hand. If you like TypeScript, you like holding things' hands.
JASON: So another thing to note here is that this one is actually better than it would usually be if you're not interpolating values because we're pulling the value of the range, which is like scrubbing up and down pixel by pixel. So it still looks like it's animating. But if you were like hitting a toggle between off and on --
ADAM: Uncomment the hover effect there.
JASON: Oh, yeah, perfect. It's almost like you predicted this was going to be something we wanted to demonstrate. So let me take this down. Then we're going to hover.
ADAM: I wonder if it's competing with the inline property. Change some HTML so it reloads a little bit. And now hover it. There. Yep.
JASON: Right. So this is because it can't interpolate. It doesn't know how to -- actually, you know what we should do. Can you define interpolation?
ADAM: Yes. Interpolation is a way to go from one state to another state over time, given a duration and an easing. So it's like when you walk from here to there, you did it over four seconds.
JASON: And each second, you moved -- like if the distance between here and there is one foot, you have to do the math to go like how did I go an inch and then the next inch. If it's linear, it's like one inch per whatever the subset of time is. If it's ease in, out, it's more inches early, fewer in the middle, and more inches at the end. So what we're hoping for is the interpolation that makes this work really nice. But because we don't have the types here, CSS is like I don't know what that is so I'm going to pop between the two values. So instead, we do the properties here. Let me fix that so it is not nonsense anymore. And now CSS knows how to interpolate. Gorgeous. All right. So we managed to use a solid 45 minutes doing that. So we got to go fast. All right. No more tangents, chat. Geez. Focus up. All right. What happens next?
ADAM: Go to gradient.style. I'll try to be quick here. So gradient.style is a website I built to empower you about gradients, to know the properties you can use, to have a visual editor, also some really, really cool stuff. Here, I want you to select the radio gradient because this'll lead us into the next demo and then the final demo that we're building here today. So here's a radio gradient. It's positioned in the center. You're changing the color stop right now. I built this thing with Svelte. Of the all the frameworks I've used over and over, I really like that one. I want you to go to the right where there's the two stops in boxes and drag all their sliders to zero. Now the slider in the middle between those two boxes --
JASON: Wait. What am I doing?
ADAM: Go between those two.
JASON: Oh, I got you.
ADAM: Yeah, now drag that one. This is called a transition hint. It's a seldom-used feature of gradients. It's kind of like easing, but it's rudimentary. What we're seeing here is I have two color stops, and they're both trying to be in the center. With the transition hint, I get to do a lot of the same kind of articulation that I would if I said that the second stop is 200 pixels from the middle or whatever. But instead, I get to use a percentage. So it's going to go from the size of the gradient -- we can see how big the gradient wants to be. We're telling it the middle point. Since we set the second one to zero, it's a hard-stop gradient. Now, I want you also to take the turquoise color and make it transparent. So just click it and put #0000. Yep. Now drag that middle size up and down. This is the crux of the effect that we're building today. We're taking gradients, making them hard stops, and then we're going to change that transition hint with some dynamic data, with our sound, with our voices. Our voices are going to wig that will thing up and down, and then we're going to create some cool effects with it.
JASON: It's good. Yeah, we warmed up last night. It's going to be great. All right. Let's go.
ADAM: Let's go. Okay. So you can close out of gradient.style. There's another demo in the document, which brings us into the next one here. Boom. Okay.
JASON: Not allowed to fork? How dare you.
ADAM: Now, this should look pretty familiar. Slide it up big and small. It's got the same springy effect on it. So we took the first demo we made where we used app property and used a slider and transitioned a box shadow, just because it was a nice scalpel-like intro. We've done the exact same thing but this time against a gradient on a transition hint. Now we're getting this black-and-white experience. You can also imagine this experience could be used to mask things. You could the mask an bouncing and really reactive, connecting with your DOM.
JASON: So this is the same code. It's just instead of having the box shadow, we're just using a background image. Two ways to solve a similar problem. We get a circle now instead of a square. Looks dope.
ADAM: Pretty fun. And just look at that grade gent syntax. We're setting the stop to position zero. We have our scalpel, our transitioning property there in the middle. That's where the transition hint goes, between two stops. Then we say white zero. Very, very simple. But we're going to turn this into some awesome, awesome stuff.
JASON: I'm so ready. All right. So we have the basics. We know what a property is. We know why they're important, why we use this syntax here. We've got our radio gradient set up. We've got a little trick here to decide how big the gradient is. Now we've got these bouncy circles. I'm ready. Let's go into the chaos. What happens next?
ADAM: Yeah, what do I have in the document next? I'm like, oh, it's time to look at some code. Oh, no. Open up the -- is it that app property gradient prototype? Yeah.
JASON: This one?
ADAM: Yeah. So this is where I started connecting your microphone input to the gradient positions. But I did another thing, which is I split -- okay. You can see the custom properties. There's two frequencies. Oh, is it just one? Oh, because this is the demo. So this demo only has one gradient, but as you enable your mic and speak into it, you'll now be changing the transition hint with your voice.
JASON: Oh, wait. We have to do this in debug mode, right?
ADAM: Yeah, the iframe doesn't like the --
JASON: Uh-oh. You might have to open this one so I can get to it.
ADAM: Is it private? Did I do that? View page source.
JASON: Maybe I can just copy the frame. Will it let me copy link address?
ADAM: There we go. Yeah.
JASON: So now we've got audio coming in from the mics, which as I'm talking, it's affecting the thing. And we're running all of the audio from the whole show. So Adam's mic, my mic, anything else we have plugged in -- hint, hint -- will all affect this gradient.
ADAM: Yep.
JASON: It shows me all of my different input devices. Actually, we probably should have done a trigger warning.
ADAM: There's a lot of motion.
JASON: Okay. Hold on. Stopping now, just in case. The rest of the show is going to have a lot of this. So if the flashing is a problem for you, please do just be aware of that. I think it's going to be this black and white, lots of pulsing to audio and stuff. Just a little trigger warning before we continue, in case that is a problem for you.
ADAM: It's not a strobe like a Pokémon episode.
JASON: But this is strobing a lot. Just be aware. Sorry I didn't say that before I started this mic. With that, I'm going to turn the mic back on. So, last warning. Okay. This is fun. It's already fun. So, talk me through how this works.
ADAM: All right. You enable the mic. You get access to the different -- so you can pull up the JavaScript, if you like. You get access to the inputs. You choose the default input. Then you start observing the stream. You observe the data and use request animation frame to set a custom property looking at that data.
JASON: Okay. So looking here, we've got this function to list devices. This goes in and gets the media device. This is all platform stuff, by the way. This is just stuff you can do. It's going to grab a list, create our list of options. What is this?
ADAM: What you doing there? Looks like a typo. Is it still working?
JASON: It is still working. Fascinating.
ADAM: Yay for tolerance.
JASON: And down here on input -- okay. So on input, we start the microphone. Then down here, let's see. Get the user media, audio gain control, so on and so forth. All right. So now --
ADAM: So we need an audio context. That allows us to start tracking an audio stream. We have mic low and mic high. So that's taking the device ID, and it's going to split the stream. It's observing the same stream. I'm going to split them up. I'm going to put a filter on them, a high-pass filter and a low-pass filter. This is going to give me two distinct ranges of your voice. The upper bounds and the lower bounds. I'm going it map those two a gradient. So it's not just a circle growing. And it's just fun to split the stream into two different types of data for me to play with.
JASON: Right, right. And so effectively, there's a little duplication here where you got to do some -- like, you have to understand how audio works. So if you've never heard words like high pass and you're not sure what these frequency numbers mean, sorry. Music is hard. Audio is very challenging. But then, we go through, set up the high-pass filter. We're looking for sounds in the 3,000 range and the 1500 range. We get into the mic. We connect here. Good. And this is just setting up these filters.
ADAM: I love that word, though. Create biquad filter. I use that all the time. I definitely didn't have to learn and look that up.
JASON: Sometimes when I think I'm really smart, I look at how musicians do all their audio mixing. Then I remember I just know a lot of jargon. When I read music stuff it's like, this must be what I sound like when other people listen to me talk.
ADAM: Totally.
JASON: So then we get -- what is this? What is this actually called?
ADAM: A buffer.
JASON: A buffer. That was the word escaping my brain. We get both of these into a buffer for our low and high. Then down here, we're reading the mic stream. So we get the value out of the buffer.
ADAM: Yep. Then at line 125, you'll see if we have a connected device, then we're going to request animation frame and keep reading the buffer at the frame rate that we can animate with. And that's how we get our data flow, and that's what we're going to pipe into PartyKit so multiple people are going to be sending their data to PartyKit, streaming to everyone else who's connected, and we're going to see a combination of chaotic, ephemeral audio experience that's also silent. It's a visual thing.
JASON: Yeah, so this is great. Basically, what we did in the first example, where based on the range value we are updating a CSS variable, this is technically the same thing. We're using JavaScript to update a CSS property based on something that's happening in the browser. It's just a little more work to get frequency values out of a microphone. But the concept stays the same. What we've accomplished here is ultimately get some value from JavaScript, whether it's the value of an input, the value of the current audio coming through the microphone. You could do this with really anything, right? Position of a mouse. You could do it with all sorts of stuff. Then you just update this value. If it's something that's not an input on screen, you do it with request animation frame to prevent locking up the main thread. And to get, like, usually around, what, 120 frames per second or so.
ADAM: Depends on the screen refresh rate. It's like a polite way of saying as fast as you can, buddy. It's hard to not dig into all this. This is the HTML element. We did lose something, though. So we don't -- we're not using app property anymore. Because we don't need to interpolate it because we are hand holding it with request animation frame. So RAF has removed our need for it.
JASON: Yeah, because we've kind of taken it out.
ADAM: So it's there but not being used. That's just my bad. But it didn't make any sense. If you're sitting there pounding it with new values, you don't need to interpolate anywhere. In fact, it didn't even do anything. It was so rapid. Then the background, that's the hot part of the design.
JASON: This is the fun stuff because once we get out here, difference means -- where is it actually? So difference means that it basically takes the first color value and then the color value under it and does the math to figure out, like, what's the opposite color. So right now, you get black and white. If we start changing colors, it's going to get fun.
ADAM: Do it. Put a color on that, right now.
JASON: Let's do it. I'm going to set the -- which piece actually has the color on it?
ADAM: Let's see. What's a good one to do? Maybe the background. The whole page could be fun to put a color on.
JASON: Where is it pulling the color from?
ADAM: I think it's in the gradient itself, which is on the HTML element. Oh, look, you can see the custom properties dancing.
JASON: Yeah, this is really cool to see. Background color, black. All right. So let's make this hot pink. Check, check. That didn't work. Why didn't that work? Hot pink.
ADAM: I don't know. What is the selector that's looking at right now? Oh, is dev tools not --
JASON: Yeah, it's fighting me. It's fighting me probably for reasons that have nothing to do with this actual demo. Let's allow again. Check, check, check. And we have our body HTML. Show me the color. Background, hot pink. How dare you. You know what --
ADAM: Let's skip it. So, one of the reasons that the experience in the design is black and white is because I tried with color, and you could get some cool psychedelic effects, but there was also times where you couldn't see anything at all, where difference was having no effect. It kind of bums me out. If I stuck to black and white, I was able to really get high contrast, a brutalist design that was always looking cool.
JASON: Yeah. Yeah, yeah. So, lots and lots of cool stuff here. What should we do next?
ADAM: All right. Check the doc. Let's see. Is it time to make the site live? It's time to see what does it look like if we take that audio stream from us, connect it in PartyKit with everyone else, pipe it through a Svelte kit app, host it in Netlify, create rooms for people to join, and create an experience. So we're going to make this thing have not an obfuscated name right now.
JASON: Site name, that's what I want. Manage site name and thumbnail. We're going to call this noisy.
ADAM: Here's the test.
JASON: We are now live. So I'm going to -- let's see. I'm going to start -- I love that you used -- so I'm going to send this to everyone. Now is the time to start participating.
ADAM: If you're one of the first nine to join, your gradient will be visualized.
JASON: Yes.
ADAM: Cool. We have folks pumping in.
JASON: Here come people.
ADAM: I see other people talking. Hit the six dots and change your gradient. Look at us all clashing and colliding. There we go.
JASON: All right, all right. Now we have some conic ones. A little chaos there. This is good. All right. Let's go back to radial. Fun.
ADAM: This is what I wanted. Yes.
JASON: This is so good. So, next here's what I want to do. Adam, could you please play us a little tune?
ADAM: Yes. You ready?
JASON: Do you want to talk about what this is also?
ADAM: This is a pocket operator. Teenage engineering. This is totally it. This thing is credit-card sized basically. The buttons -- I mean, you could probably shock your hands on the back. I don't know. I haven't yet, but all of the soldering is exposed. This is the pocket operator megaman. It's legit, dude. Let's see if I can come up with a cool rift to put through this channel.
JASON: This is great. All right. But I want more. I want more.
ADAM: All right. Here we go. We've gotten a electric guitar. This is untested. I don't know what it's going to look like, but I'm assuming it's going to look pretty sweet. All right. Turn the volume up there.
JASON: Let me unmute it. (Electric guitar playing)
ADAM: Do we need to choose it as the input there?
JASON: Oh, no, it's going.
ADAM: Oh, sweet. So there you all go. We got some shredding. Yeah, no "Stairway to Heaven."
JASON: So what's really magical about this is that if we look at what's happening, like if we really dig into what's going on in the code itself -- let me mute that again. There we go. So if we look at what's actually happening in the code -- let's go to the actual repo. Why not, right? Here's the repo, if anybody wants to go.
ADAM: Oh, it is public. It's been public.
JASON: It's been public the whole time. Surprise! So let's dive into what this is actually doing. Talk me through what we're -- like where should I like? What's going on in here?
ADAM: Yeah, peep the components. The icons are going to be not very surprising. They're just icons. What's a lib? I forgot. Oh, yeah. Okay. So this is just different stores and stuff like that. So this is like a Svelte kit architecture. What is our main component?
JASON: Main component is probably here, right?
ADAM: Yeah, so we have the homepage and then that route page. Svelte gives me access to the URL variables very easily. So we have an action that just looks at the URL, passes it down to this component for rendering on the server side. And I can access it there on 22, export let data. So Svelte gives me the metadata from the room, which I can connect to PartyKit. You can see a lot of the same code, like we're managing a device list. The vanilla version I made is fed directly into the Svelte kit version here.
JASON: And so the device media here is -- like, here's our list of audio devices. Looks pretty similar. I think it's exactly the same. Then we've got --
ADAM: These are the different linear gradients. There's the radial and the conic. So depending on how you change your settings, I invoke a function, pass in the type you're looking for, and then feed it a little bit of data, like this prefix that you see here. Once I defined the gradients, it's kind of fun from there. They're each using the low and high in different ways. So at that point, I got to get really playful in the effects. People could add more if they like.
JASON: Yeah, and this is where you could also start playing with the colors and kind of override some of this stuff.
ADAM: Yep, exactly.
JASON: Just to see what you can come up with. So then in the PartyKit stuff, and this is where I think it gets really interesting, let's see how much code there is to make this fully -- less than 100 lines to go full multiplayer. Is there more PartyKit hidden around?
ADAM: There's the server. If you go to the left and scroll to the top, there's the PartyKit folder here. You need to run this locally. Go to source and look at server.ts. This is the server.
JASON: Okay. So about 150 lines so far. And a lot of this is -- so when you come through, you're sending events. When you connect, you've got to make sure you're in the right room. Didn't mean to do that. Then you push in your connection ID, update the count.
ADAM: So you saw live, as people joined, we saw the number tick up. And as they disconnected. So the server is managing the number of connections and managing the IDs of these folks as well. And JSON parsing the data back and forth as I transfer it.
JASON: I like that you call them partiers. It's fun. I like that. So then we've got -- let's see, opening up the code again.
ADAM: That's just PartyKit default stuff. I didn't use it.
JASON: Oh, perfect.
ADAM: I could have deleted it. Same with the whole public folder. I didn't need it.
JASON: Oh, right, because PartyKit has the ability to host as well.
ADAM: Yeah, they host and you can see the console logs. They do a good job of auto spinning you up a client.
JASON: Got it. So on your side, we are --
ADAM: So there's my little switch based on what kind of event. I have different types of events I'm sending. So when you connect, I update the count. When you connected your audio, I start to broadcast audio. And this was a tricky part. I needed streams. I needed different channels. Instead of making multiple sockets, I used the same socket and pumped things over it. That's why they're in upper case.
JASON: Then this audio here, we're getting the same low and high data, but we're able to quite literally just send those values to everybody connected to the site. This is happening fast enough that, like, it wouldn't be realtime. You couldn't play songs together. But it's so close to realtime you kind of can't tell unless you're listening for actual sync, which is kind of mind boggling, honestly, how nice that web socket experience is. Granted, we're limited by physics. Me here, someone in Australia. The speed of light is going to add notable delay there. But if you're sitting next to step, you know, in the same -- even just North America, the delay is so low. It's so cool. You can play realtime games. It's like when you play Fortnite or whatever. It's almost to the point of not being noticeable.
ADAM: Yeah, so you can see there in the audio when it says partiers, that's a Svelte thing. Then for each partier, I'm looking at the value of their data and setting a custom property. The custom property has partier ID, on line 60. That's how every partyer has their own unique ID. I feed each of those into the page. As we had ten people connected, it was updating 20 custom properties on your page. The custom properties are requesting animation framing and being presented to you, and you get this audio experience. Super-duper cool. Then down there, the gradients ones, line 73. That is another broadcast event. You changed your gradient, and I need to change it for everyone subscribed to the channel. So as we switched from gradient, it wasn't just us seeing the local change. We broadcast it. I update the gradient by invoking the effect you saw earlier, the gradient effect, and change the gradient on your page for everyone else. So there's a lot of multitenancy things to do. I felt like I was doing more on the client than I needed to in some ways. But at the end of the day, I think I had a decent separation of concerns here.
JASON: Yeah, at the end of the day, this is what probably 300-ish lines of code, maybe 400 lines of code to build a realtime multiplayer, audio aware, animated -- like, there's just a lot going on in not that much space. It really is -- like, this is a very cool thing to build with what doesn't feel intimidating to me, amount of work. I think the most intimidating part is wrestling the audio, the specifics of audio, just because that is a very challenging place. Understanding frequencies and how to get out of the sound going into the microphone, how do you turn that into numbers that you can play with. Fortunately, lots of things to copy/paste out there that will help you do exactly that.
ADAM: Yep. Let's see. What are some other good things to talk about?
JASON: CSS-Pong based on how loud the audio is. Please build that. That is a great idea. You'd have to -- so if it was frequency based, if you want it to be all the way at the bottom when you're quiet and all the way top, like (yelling).
ADAM: Oh, there's a fun test you can do out there. There's four hidden Easter eggs.
JASON: Oh, can we find them?
ADAM: So let's see. Challenge out there, everybody. There's one.
JASON: Oh, we found one?
ADAM: Yeah, that one I'm calling life after death.
JASON: Oh, like somebody disconnects in the middle of making noise.
ADAM: Yes, precisely.
JASON: Ah, okay, okay. So you freeze wherever it was.
ADAM: I didn't do that. I just didn't fix it.
JASON: (Laughter)
ADAM: Because technically, what everyone could do is connect to room 1337 right now, enable your mic, make some noise, and disable your mic. You would leave yourself permanently on the screen, and theoretically, we could get a bunch of permanents. At least that's the theory. So that's one of the four Easter eggs, life after death. Another one is called turquoise. See if you can find the color turquoise.
JASON: Find the color turquoise?
ADAM: Yeah, because look, it's a black and white app. Where the hell could turquoise be? It's not in the code. It's in the experience. Maybe someone in the chat will find it. Maybe someone in the chat has already stumbled upon it.
JASON: Find the color turquoise? And it's not like in the edges, like where the animation, if you screenshot it -- wait, did I just see it? Hold on.
ADAM: It's not there.
JASON: No? All right. Oh! Okay.
ADAM: You've got to be talking white the red of the button is shown, and it inverts it into turquoise.
JASON: Oh, I didn't even realize that was what was happening. Neat. Okay. Okay. All right.
ADAM: There's two more. Check the doc.
JASON: What did you call them?
ADAM: They had clever names. At least I thought they were clever.
JASON: Give it the time of day and take me with you. So, time of day. How would you do that? Let's see. Give it the -- oh, no. No, come back. Give it the time of day.
ADAM: Yeah, you know, in the morning it's light and at night it's dark.
JASON: How dare you. I'm going to -- (Laughter) Okay. I went to light mode, and I think I broke it. Do I need to refresh?
ADAM: No, this is just kind of the deal. The light mode and the dark mode have an inverse of interaction. It's just fun to see the deference there. So now we have like an inverted experience, which is still kind of cool. I like the life after death. It's like intersecting right now. That looks really cool. And the last one is take me with you. Take me with you is while your mic is enabled, click the back button to go to the homepage.
JASON: So, like -- ahhhh. Look at that. Look at it go.
ADAM: So you still have your mic enabled, and I'm still pumping it into a gradient on the page just for you to see in the experience here.
JASON: That's really fun. I mean, this is the sort of thing -- it's a way to play. It's not wildly complicated. You're not having to, like -- I don't know. I feel like a lot of times when I try to think of a demo, I feel the pressure to be, like, really unique. Like, I need to build something that's never existed before. I have to invent something from scratch. First of all, there's probably very few things left with the current platform state that are net new. There's a finite set of things that can be done. Probably somebody has built something with each of these features that's pretty close to what you're imagining. So instead, you're looking for different combinations that are clever or interesting, embracing the constraints of that instead of feeling overwhelmed or helpless, like I'll never come up with anything original. That's okay. You don't need to come up with something original. Just remix what's there and have fun with it. In doing that, you come up with something -- this is absolutely original. I don't think this particular thing has ever existed before. But it's all built with stuff that we've seen in different places. And I love that. I think that makes for really special experiences, when you can find a simple way to remix the things that we already know that is surprising or delightful. The fact this is the microphone driving CSS, I didn't know that I would have guessed -- that wasn't on my BINGO card.
ADAM: All right. There's one more Easter egg. Go to the home screen and refresh. Okay. So just let it sit there.
JASON: Okay.
ADAM: This would have been discovered by anybody who just like opened it up and were like, I don't know if I even want to try. This is lame. Well, after 20 seconds, I animate @property in those corners and just give some life to this. So there's the springy animation. This is a call back to us in the beginning. A call back to the original thought, the original intersection of difference in the blend modes, seeing a custom property be animated and just makes the page feel like static after it has sat for a bit.
JASON: This is great. I mean, this is so fun. I like the way that Linda said this. It's both intimidating, because there's a lot going on, it's very cool, but also, it doesn't feel out of reach. I understand each component part. So the challenge here is in seeing how things fit together, not in having to learn a lot of complicated things in order to get it done. I think that does -- these are my favorite kind of demos. It didn't take us -- you know, we're not scrambling to get to the end of time to make this work. Obviously, we cheated a little bit by having the code pre-deployed. But at the same time, when you look at what this code is doing, most of what we wrote is presentational. It's like making -- you know, it's the styles. It's the actual DOM elements. The interaction itself lives in this CodePen. Not this one. This one. It's just really not -- you know, like 130-ish lines of code of straight-up vanilla JS. The vast majority of it is this audio wrangling.
ADAM: It's the splitting of the stream. The stream split! I karate chop it. It's coming in, and you just say "hi-ya."
JASON: Also in here looking at this CSS, even with the craft, it's under 150 lines.
ADAM: Hey, scroll up there. There's a gradient commented out above the radial. That one. That will bring color in. Look, lime and yellow. You can preview the psychedelic nature of it.
JASON: Check, check. Oh, we need to save. I can't save this. So I'm not going to be able to do it.
ADAM: Open it up in the debug mode and enable. It should be there in the HTML. If you have the HTML tag, it's selected as good. Check the styles pane. You should find the gradient. Oh, did it get cropped out?
JASON: Something is weird in here that I don't fully understand. I think this might be an artifact of me trying to escape the iframe on CodePen.
ADAM: Also, dev tools does not like I'm rapidly setting a custom property and you're like, hi, I'd like to edit this element. It's like, this element is under chaos. If you just steal that and stick it in the background image --
JASON: Does this actually -- there it is. Hey, look at that. Okay. Some color. So this is a little built of hacking on CodePen. The reason we're doing this is that you can't -- you know, I don't know how to pass the audio context into an iframe. I don't know if it works. We weren't able to figure it out. So you have to get past the iframe.
ADAM: We have a gradient that also has difference. Now we're just getting this fun psychedelic experience. You can imagine, I was testing this out in the big one that had all the corners and all the different stuff. It was cool. It was psychedelic. But at the same time, a lot of -- there was data loss. That's what was sad. Certain colors -- yeah, don't cross streams.
JASON: This is a lot of fun. I'm going to stop this. Let's go back to --
ADAM: Yeah, we can check out more code, if we want to look at some of the Svelte stuff in there.
JASON: We're starting to come down to the end. Instead of getting deeper into the code, because that'll definitely cause me to run over time, let's instead do some further reading and resources for folks. So I'm going to start by sending over the @property. We shared that earlier. We have the mdn.io/audiocontext. Is that one going to work? Yeah, it is.
ADAM: That is rad.
JASON: There's the audio context, if you want to get in and learn that. We used some Svelte Kit. Gradient.style, which I think I still have open. I'm going to copy it without the current gradient details. Where else? I'm going to throw people back to your site because that's a good little place. Oh, here's a question. Could @property be used for polyfills? Can you say more about what kind of polyfills you're thinking of?
ADAM: Yeah, what would you like to polyfill? My hunch is probably not because @property is just a typed variable. The types are pre-defined. CSS is a typed language, y'all. So those types all come from the docs that are already there. You're going to have lengths, percentages, frequencies. There's all these different types of @property opportunities. There's background images. There's URLs. So I'm not sure how you can use it to polyfill something unless the polyfill was something that needed to be typed. You can build type safety into your system with @property so someone can't break it. Like if you put the color red into the size value of the CodePen, it doesn't work. The browser goes, I'm not going to use red here. It's a length only. So it just throws away.
JASON: So it doesn't break. Like, it doesn't throw an error. It just ignores the bad input.
ADAM: It tolerates it. Classic CSS.
JASON: I think that's something that's both challenging but also very nice. CSS doesn't throw errors. It doesn't explode. It just ignores bad input.
ADAM: I love that it's fault tolerant. A lot of people would want it to break. JavaScript, I always feel like it's weird. You're doing this powerful thing, and one little character throws the whole thing off. But CSS is tolerant. It'll keep moving. Did they specify the polyfills?
JASON: I think it was thinking about the CSS Houdini API. You can't use CSS properties because they have to be supported in the browser. So you can't bring them back or whatever.
ADAM: @property is part of the Houdini spec. This also is going to be in Firefox soon. Safari already has it. The paint API doesn't need @property, but @property types the parameters that get fed into the paint API. So you have this circle of typed information that you could use when you're painting from the Houdini API on to Canvas. You had confidence that the variables that you were getting in, the parameters being passed to your function weren't going to break your logic.
JASON: Excellent. Okay. Let's see. We are just about at time here. So, chat, now is your opportunity. Do you have questions? If you have questions, get them in right now. Adam, is there anything we want to cover, any other details we want to share, any other links or resources?
ADAM: The doc had a couple additional notes. I had some architecture things. I wanted originally to use Astro, but then once I needed rooms and there was this concept of, like, oh, I'm not statically generating it, then I was like, but wait, I could make it a single-page app. Actually, Svelte Kit does a hybrid thing. When you go to a room and hit back -- the reason life after death exists is because Svelte Kit is making changes to the page.
JASON: Oh, here's a great question. Where can someone go find that list of colors, like highlight and the other system colors?
ADAM: They're called system colors. You'll find them in a CSS spec. MDN probably has a good list. There they are. Accent color and accent color text are under -- they're not in every browser. Active text, button border. Look at button face. It's butt-on-face. Someone that was more mature than me named that. Okay. So canvas and canvas text, I use those all the time. Canvass can be whatever the browser is using as the background color for the document. Canvas text is whatever the text color is. So you're guaranteed a contrasting experience that also is light and dark. Really nice.
JASON: Yeah. And the nice thing about this is I lean on inherit a lot, but sometimes you're not inheriting because you're a couple layers in or whatever. I want to have my footer be light and dark, but I don't necessarily want to have a footer color and body text color. So knowing that if I set my body to have text color and background color, then these will carry that through in a way that updates without me having to change variables, without me having to do really anything other than know that I've set those somewhere in the document. That's good.
ADAM: You do need color scheme to opt your document into the light and dark default browser styles.
JASON: Right. Right, right.
ADAM: Otherwise, it'll just be a light theme.
JASON: Got it. Okay.
ADAM: And color scheme is cool too because it tints all your inputs. All the radio inputs and check boxes, the color scheme property will make them dark.
JASON: So good. Very, very, very good.
ADAM: Great question, though.
JASON: Thank you, Linda. I appreciate that. That's very nice. Always appreciate the content. Thank you, thank you, thank you. Adam, where should people go if they want to learn more not about this but about you specifically? I've linked to your site. Where else?
ADAM: I have an RSS feed. If you don't want to deal with the social network and get it straight from the stream, there it is.
JASON: Look at it go. And actually, linked right on the front of the site. I wrote a whole post about missing RSS. I'm very happy to see that come back. This is a nice little effect. Look at that.
ADAM: Yeah, it's an exploding box shadow.
JASON: Because why not, right? Why not?
ADAM: I think each one is a different color, too, at the top. Anyway, find me on Twitter if you want more. I tend to tweet more than I post on my own site. My site tends to be leaner, and Twitter tends to be a little bit noisier. I'll also repost things there, and I don't tend to repost on my personal blog. You can find me on Blue Sky. Find me on Mastodon as well. I've also got a couple podcasts. I'm on the CSS podcast. I already shouted this out. That's Una and I breaking down CSS, the computer science side of it. We really dig into the details of the specs and the full features of a particular API of CSS. If you want to really dig in and get your mind blown, I think we make it really approachable. So it's not dry. Then I have a sillier one, which Jason has been on, called the bad at CSS podcast. It's pretty new. We're still making a website.
JASON: Here's a link.
ADAM: That one gets sillier. We sit around and talk about how hard CSS is. By doing so and explaining the things that were difficult, we end up learning from people because we're like, I didn't even know that was possible. And they're over there struggling with it. So you get this nice feedback loop of people being humble but also simultaneously teaching you kind of cool stuff. Those are the great places to start. Also, the Chrome developers blog. I'm constantly on there. My job is CSS at Chrome. As new CSS lands in Chrome, you'll find it there first. If you want stuff and you want to sip from the source, this is where you want to go. Una and I and Bramis, we're on here posting the latest and greatest. We go into great detail.
JASON: Love it. All right. And I saw a question about where can I rewatch. Easiest play is if you go to the Learn With Jason YouTube and click this live tab. You can find everything there. This episode will be rewatchable right away, as soon as we go off. You'll be able to start it from the beginning and watch. I can actually just give a little link to that in the chat, for anybody who needs it.
ADAM: Also, share that Noisee link with your friends. If you're remote working with people right now, send them that link to a room. Tell them to enable their mic. And you can just sit there and have an ephemeral, silly moment together in this brutalist noise experiment.
JASON: And this is actually a fun application of this I was just thinking of. If you were on a meeting and you want non-disruptive participation, you could basically have the team sit in a thing like this so that they can all be muted in the call, but as they see different things, they can make noise and the page will show the excitement of the team. Like an announcement meeting or something. There's a lot of fun ways this could be used and played with. Yes. Excellent. This is awesome. So Adam, we're out of time. Chat, we're out of time. Make sure you head over to the website. This episode, like every episode -- this is not the thing I wanted to scroll through. There we go. This episode has been sponsored by Netlify and Vets Who Code. Thank you, both, very much for making this possible. The transcript today -- we had a little scheduling issue. So we didn't have the live transcript today. Usually we have live transcription, which we'll make sure we get transcription into this episode. We'll use the robots to do it this time. While you're on the website, make sure you check out the schedule because we've got nothing listed yet. Okay. Go here and hit the calendar button or pay attention on Discord, YouTube, wherever. I have new episodes scheduled I just haven't put on the website yet because I get lazy sometimes.
ADAM: How dare you.
JASON: I'm sorry. I'm sorry. All right. Any parting words for the chat, Adam?
ADAM: Dude, this was so much fun. Thank you for inviting me. I had a blast making this. I basically spent a week making something silly. I got to share it with you. What an amazing experience. I really appreciate this. Dude, you rock. My favorite on the web.
JASON: One more in-person high five.
ADAM: Hi-ya!
JASON: Yes! All right. Thank you all so much for hanging out. Hopefully we'll be able to do more of these in-person Learn With Jason episodes in the future. Tell your boss, they should be sponsors this show so I can afford to bring people out here. With that, thanks for hanging out, friends. We'll see you next time.