skip to content

Let's Learn Motion DevTools!

Build, inspect, edit, and export animations made with CSS and Motion One using this Chrome extension from the Motion team. Matt Perry will show us how it works.

Full Transcript

Click to toggle the visibility of the 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.

JASON: Hello, everyone, and welcome to another episode of Learn With Jason. Today on the show, we are bringing back Matt Perry. Matt, how you doing?

MATT: Yeah, I'm good. Thanks. How you doing?

JASON: I'm doing great. I'm excited to have you back. I feel like it is always a pleasure to have you on the show because you do things that make my head spin, and that always is a lot of fun for us. So for folks who aren't familiar with your work, do you want to give us a bit of a background?

MATT: Yeah, I'll give this because we were just talking. It can get confusing. I've done so many animation libraries, and I've managed to add the word motion into all of them. I initially started writing pop motion, which is like a JavaScript animation library, but it's very low level.

JASON: We're just going to do the count here.

MATT: What's the count?

JASON: Pop motion. That's one library with motion.

MATT: Hope you've got some hands.

JASON: (Laughter)

MATT: Actually, this should just about fit on one. So we've got pop motion. Low-level JavaScript animation. But then I built one called pose.

JASON: No motion.

MATT: That was probably the only one. Sometimes I call it pop motion pose. I don't know if that counts.

JASON: We'll count it.

MATT: And that was a stab at a declarative, React-based animation library. But it worked with Vue and some other things as well. Then I started working for Framer, who make an amazing website builder tool, which you should all check out. Framer.com. I still make framer motion, which is kind of a continuation of pose. It's a React animation library. And now, alongside that, it's kind of like a side project. It started as an experiment with the web animations API, I'm building Motion One, which is the last animation library. But obviously, here today, I'm here to talk about Motion DevTools, which is the fifth and final use of motion.

JASON: Didn't have to use a single toe.

MATT: Exactly, yeah. So Motion One is an animation library, sort of meant to be a quick way to describe it is the jQuery of WAPI. It's there to smooth over the consistencies between various browser implementations. They don't all support the same feature sets.

JASON: Gotcha.

MATT: So there are things like the finish. All these tiny implementation details. And it's also there to expand its capabilities. For instance, we can do spring animations with independent transforms. Neither of those things are possible in CSS or WAPI. We're trying to leverage the fact that we're using WAPI. By using WAPI, we get a lot of things for free. Like, say, we can interpolate or animate between complex values like 100 pixels and calc times 50 or something. Which you can't do in any JavaScript library. In the situations where you can -- like Framer Motion is a good example. We're applying one set of values -- both sets of value, measuring it, and animating in pixels, which isn't always bulletproof. When you do it via the native browser APIs, you get it for free in terms of file size and runtime performance. So it was an experiment just to see how much we can get out of WAPI and how many limitations we can surpass, basically. And it might be --

JASON: Yeah. This is really exciting. I mean, we can tell that it's exciting because we're seeing a lot of first timers in the chat. So welcome to all the folks who are here for the first time. Thank you for tuning in. This is going to be great. And thank you Xander for gifting five subs. Super appreciated. Thank you very much. People are making jokes about what your next motion library is going to be called. Return of the motion, the motion strikes back.

MATT: Yeah, if it goes by the Xbox naming convention, the next one has got to be like motion series X. We've got back. Motion One is like the fourth one.

JASON: Oh, yeah, yeah, yeah. Okay. All right. So now we need, like, two motion two animated. Motion Tokyo drift. (Laughter)

MATT: Yeah, which is the best one.

JASON: All right. So when we talk about all of these -- so we've got Framer Motion, which is a -- that one is React specific or is that framework agnostic?

MATT: Yeah, React specific. To sort of contextualize it, it's also built on Pop Motion. When I say Pop Motion is a low-level animation library, you can build something like Framer Motion on it. In that sense, Motion One is meant to be more like the new Pop Motion than the new Framer Motion. So what I'm trying to work towards is you could build today like a React animation library straight off of Motion One. I've kind of done that with Vue. If you go to motion.dev, we have Vue, we have Solid wrappers. I'm quietly working on a Svelte one as well. I don't know where I've left that, to be honest. But the idea is, hopefully, to get Motion One into Framer Motion as a replacement for Pop Motion. Then we can start leveraging things like a smaller file size or its ability to run animations off the main animation thread or the complex value type interpolation I was talking about before. But it poses some problems in that there are some limitations with WAPI that sort of don't exist, you know, with normal JavaScript animation libraries. So it's not like Motion One is a superset of functionality of pop motion. So just by removing it, we have some considerations there. As I remove more of these limitations, we're getting closer to Motion One into Framer Motion.

JASON: Got you. And when you're saying WAPI, that's short for web animations API, right?

MATT: Yeah, sorry. Like every browser basically comes with a JavaScript animation library in it, which is crazy. As someone who's being writing for these for years, I thought this is actually kind of crazy we don't use it always. So I started playing around with it, thinking maybe it's an education thing. When I used it, I ran into so many cross-browser problems, blah, blah, blah, that this is how I ended up writing Motion One in the first place.

JASON: And so you mentioned that this is kind of like the jQuery for WAAPI, which is an apt description because jQuery existed because the implementation between browser was needed to smooth out the usage. You're looking at the way, say, Firefox or Chrome implement the same API and their subtle differences in how they work. Then you're making it so that if I use one method, it's the same on Chrome, Firefox, wherever we want to implement.

MATT: Yeah, exactly. And in some ways, the same way that jQuery is always an edit of some APIs. It's a bit of an edit. So the scroll linked animations just released is a good example. I've been looking into the progression of -- like the same way we have WAAPI, we're going to get upcoming scroll-linked animation APIs which is pretty exciting. But I didn't necessarily like the way -- you know, it's personal preference. I personally didn't love the API was shaping up. I thought it would be nice to do my sort of -- how I'd like to see it but do it in a way that under the hood when these APIs are finished, we can sort of plug those in quietly, like without anyone noticing. So in the browsers where it's supported, we'll run it on the browser's scroll-link animation libraries. And where they're not supported, we still have that JavaScript implementation we can leverage.

JASON: Got it. No, I love that. And to me, that's always what makes this stuff nice. And it feels like this is the way I like to see userland libraries and platforms kind of work together. The platforms put some tools out there. They're building what they need for their specific platform. Then user goes out and looks at what the platforms are building and put together a more cohesive version. Hey, this is what we need in real life. Then the platforms can observe that and pull the pieces that make sense back into the platform. And this is what we saw with jQuery, where jQuery was kind of a superset of the JavaScript browser APIs. And a lot of the most useful bits have been built back into the spec. Query selector and a handful of things that jQuery offered are now part of the spec, which is wonderful. It's such a good collaboration between the browser vendors and the people working on client code. All right, I need these things, so I'm going to use a library that does these things. The browsers are saying, great, we see you need those thing, and this is implemented well. Everybody can agree on it, so we're going to pull that back into the spec to decrease the amount of client-side JavaScript you've got to load. On and on. It just becomes this great collaborative, upward cycle where we all win in the end.

MATT: Yeah, I think so.

JASON: Do you end up having a lot of conversations with the WAAPI spec team?

MATT: Not overly. It will always be to sort of -- actually, everyone that I've spoken to is super helpful and stuff if you've got questions about how was this implemented, why was it like this. One thing I would say is I've been writing animation libraries for years. We've got Jack from GreenSock. He's been doing it for literally decades. I didn't see any discussion about that in these spec conversations. Do you know what I mean? I find that crazy. I haven't seen a single mention of GreenSock's scroll trigger. This is native. Boom. You're done. So I haven't actually been that involved. And sometimes when someone used to work predominantly -- I find that it's often quite an isolated, you know, very focused. Obviously you work with other people and stuff, but it's often a very hyper focused part to work in. It can be, even from my point of view, it's not like I see all these discussions and I'm like, man, I'd love to get involved with these. Sometimes I'll speak up. But it feels like quite a closed club and quite a -- what would I say? You know, when these things take so long because everyone is trying to decide what's best, as someone who's used to just kind of do it, you know, it can be frustrating. So it's a bit of everything. I think this may be a problem in terms of that feedback cycle, but I also think that people like me, and I don't speak for any of these other library author, but I suspect it's the same situation. You have that itch to get something done. And maybe don't feel like you need too many or want too many things that could -- you know, because sometimes it can be more confusing than not to get those other opinions.

JASON: And I think you're bringing up something that I think is important, which is that, you know, the library authors are out there seeing problems and solving those problems. They're not particularly worried about -- the concern is I have a project, and I need to solve a problem for this project. The spec authors are committed to, like, don't break the internet. So every decision they make needs to be thought of not just for how does it solve problems today but how will this live into the future, how will this affect things that were done in the past, is this going to break backward compatibility. There's all these concerns that necessarily slow down those decisions. This is actually something that I find to be one of the healthiest parts of the open source to platform relationship. Like, I, as a developer, would like to use the platform, but there are a lot of things I need to build today that aren't built into the platform. You mentioned scroll trigger. What a killer intervention. Just an absolutely wonderful feature. When I saw it, I was like, I need that. So I look, it's not in the platform. So I can adopt GSAP, use scroll trigger today, and solve my problem. Then I hope the platform picks it up so eventually I don't need to install all of the JavaScript to run GSAP. And I still get that feature. I think on the long horizon, we're after that sort of thing. And my expectation is that you will give me Motion One, and then you'll launch a second version of it. That can break backward compatibility. That's okay. But when I adopt the web APIs, I expect I can let those things run forever and I'll never have to touch them again because they'll always work. I think that, to me, is -- I don't know. I feel like that's almost the right balance of fast to slow. I do wish there was, like, as with all situations, I wish the collaboration was just super tight and everyone was really open and wanted to work together. But I'm also very happy that we're not, like, really hauling ass on the browser specs because I don't want broken browsers.

MATT: No, absolutely. And I say this with full knowledge, that I'm working in a space where I can undo things because I can -- but when you're working in -- once it's out there, that's the situation. So there's also a freedom, I guess. But yeah, I'd rather it was slow. I think maybe the feedback loop could be better. In general, yeah, super lucky there's people out there that are taking the time to get it right the first time.

JASON: Yeah, and so let me take a slight step in a different direction here because I want to talk about using a library like Motion One, which can be kind of low level, especially for folks who, like me, don't spend a lot of time in animation. One of the things that gets really confusing for me really quickly is when I start thinking about, okay, we've got the animation, but the animation is happening on a loop. I'm not just saying take this thing and put it over here. I want it to be here. I want it to end over here. And then I want that to take a few seconds. So that means I've got to set up this kind of loop or I'm figuring out how far away it is. Now I want to do easing, so you have to do this math. It starts to get very complicated to visualize and sort of manage very quickly. So I know you've been working on tools to make the implementation of these things easier. The things that give you springs and difficult physics, animate things smoothly. But how do I debug this stuff? What's the right way to get a sense of what's actually happening so when I think it should be doing one thing and it's doing a different thing, I can start to understand what I did in my code? Because a lot of times I'm just copy/pasting and using function or looking at an example somewhere saying, oh, quantitative ease in, out seems like what I need. Let me do that. And I have no idea what it means or what it's for or if I even said it correctly just now. (Laughter)

MATT: I feel like it was correct enough.

JASON: I just made something up, apparently. Chat it letting me know.

MATT: We've been exposed to too much financial meltdown news recently. I think that's probably why. Well, I'd be interested, actually. I know that you use Edge. Is that correct? So in Chrome, there is, of course, the elements tab. You can inspect the CSS properties that have been applied to something. Which is fine, I think. If you want to just dink around with some values, for sure. What else do you have? The animations. There's an actual animations tab that you can go into and record the animations happening on the screen. So I'm here to talk about Motion DevTools, which is a developer debug panel. The same way you have your elements, your console, it's a panel on your developers tool where you can plot animations on a timeline, scroll through them, edit the key frames, move them around, and all this sort of thing. So we do actually have one built in the browser. I don't know if this is true for Edge. It would be quite interesting to see how much it takes from Chrome. But in Chrome, it's kind of limited. You can only do CSS and WAAPI, whereas Motion DevTools is here. It doesn't do frame of motion yet. We'll see. We'll probably end up doing something with this. If Motion One ends up in frame of motion, good. We've already got it. I wonder if we'll do something more specific for framer. I don't know. So we can debug the sites. I don't know what it is yet, but these are just ideas. Something more might come out of this in terms of framer. But this could be extended for any JavaScript animation library. I think the problem with the in-built tools is that lack of extensibility. And I don't know -- sorry, I'm just going to close the window. The sun is making itself known. I can't actually see anyone. Yeah, amazing light. I think I was going to be blind if I let that amazing light in. So the animation tab. The problem is there are certain things you'd expect from a timeline editor. It doesn't work so well. So you can't really scrub through the animation, I think. You can replay it. But I don't think you can start it from a specific place. Things like that. And it's easy to imagine why. I don't know how much it's used. You know, they've probably got bigger fish to fry. This is not a huge team. But yeah, so that's why I came. I was always frustrated with that lack of toolage, I guess, is probably a word. If it's not, it suits. Probably won't last beyond this last sentence. But yeah, so that's what I'm here to talk about today.

JASON: Yeah, all right. So let me actually switch us over because I think at this point, it's going to be easier to show than tell. So I'll pop us over into the pair programming view. Get this window out of the way. We'll start by doing a quick shout out to our captioning. We've got Rachel here today taking down all these words. Thank you, Rachel, for that. Over from White Coat Captioning. And that is made possible through the support of our sponsors. We have Netlify, Nx, and New Relic all kicking in to make this show more accessible to more people, which I very much appreciate. You can all go and find that on the home page of Learn With Jason if you want to follow along with the captions yourself. In addition to that, we are talking to Matt today. So you can head over to the old Twitter and get information about all animation-related things. Any library with the name "motion" in is, Matt is your man. We're talking about motion today. I already dropped a link, but I'll drop it again. Here's motion.dev. And this is the jQuery for the API. With that said, Matt, what should I look at if I want to -- so before we started, you sent me a link to download a plug-in or an extension, right? So I'll open up the Motion site because this is very cool, and I want to keep looking at it. You had Me Install Motion DevTools. That's all that I've done so far.

MATT: Brilliant. See, I've neglected this button here. I didn't really realize. I take all my extensions out of the top bar. Now that I've seen it on yours, it might be cool if we detect animation that's inspectable, which makes the icon blue. And you click.

JASON: Mm, yeah.

MATT: I don't think you can open the DevTools from it, though. That's the problem. Now maybe if you scroll down. This is quite an easy animation. Right now if you right click on this and go to inspect, I guess. Sorry, I'm not familiar with Edge. Oh, so this is Chrome. We are on Chrome. This isn't Edge anymore.

JASON: This is Edge, but it's effectively the same browser at this point.

MATT: Okay, maybe it's probably got the animation tool.

JASON: It probably does, would be my guess.

MATT: If it's possible, can we see the little chevrons at the top there? I believe that should -- so if you go up a bit. There's another chevron. There's chevrons everywhere on this. There we go. Ah, okay. I was expecting that to have more. Yeah, motion will do. I can't see the animations part.

JASON: Let's see. It might be -- oh, animations.

MATT: Oh, yeah. Okay. So if you scroll this panel, because this panel is using Motion One's in view function. When it scrolls out of the screen, it will just stop the animation so you can keep sections of your page super performant. So if you scroll out and scroll back in again, I'm curious to see -- okay. So it has got -- it looks like one of these. You can see these little thumbnails. I don't know how clear that is. So this one looks like it might be all right. Does that screenshot just get in the way every time? This is the sort of thing I'm trying to fix.

JASON: There it is.

MATT: Brilliant. So you can maybe like move the timeline, I guess. You can replay it from the beginning. Other than that, I'm not sure how much functionality there is here, especially if this is a WAAPI animation. It's got two things.

JASON: This is the circle. Okay. I was controlling the one below it. That's what was wrong. So we have our ball. Then I want to -- if I start messing with this, what happens?

MATT: So, yeah, you can move the key frames quite easily. But because this animation was built with Motion One, therefore it's in WAAPI. In the CSS property panel, there's nowhere to change the values and see what it would look like with a different scale or anything like that. And you can't -- I don't know. Maybe they've changed it. Can you scrub the animation or anything like that? So with the player head at the top there.

JASON: Doesn't look like it. Can I grab you? Stop, come here.

MATT: Oh, you can. Brilliant. I wonder if they've changed it. Yeah, so there's some stuff, I guess, some features here. But because we've done this in WAAPI, it's a bit limited. The other thing that I find kind of annoying is even when it's in CSS, you can't then hop into the elements panel and check. I mean, you can. You can have them open, but they're kind of disconnected, and it doesn't always make sense. I'm kicking on this frame. You don't really know what you're seeing at any given time. So if you close this panel, yeah.

JASON: Ah, this is what I needed to do. I moved it to the top, and now I can actually use it. So it was like a bonus feature. Now I've added it as a top feature. Okay. So now I'm clicking on motion.

MATT: Okay. Now by default, this is the motion tab. By default, in the top left you can see this little red button. That is the record button. It's on by default. When you open the tab, it's already running. So if you do the same trick as before, scroll down and scroll back again, now we have two animations. I believe this is the one because it says clip path and scale. And you can see now you can scrub between the two key frames. There should be a repeat. But anyway, you can play, you can pause, you can skip back to the beginning. But you can also, if you click on these little magnifying glasses by their names, you can go directly to the element that you're -- oh, yeah, which one is this?

JASON: Oh, I think I did something where I scrolled in and out really quickly. All right. This one has got the repeat.

MATT: Ah, that's the one. Yeah. And this will just go on forever, basically. But here, you can go in here.

JASON: Oh.

MATT: So what we're in at the moment is just called inspect mode. It's the free mode. At some point -- because I'm using a library called Leva. It's really good. It does these property controls. It's copyable even in inspect mode. But they're currently not. This one is a circle, 105 pixels. You can go directly to the element using the magnifying glass. So you know, oh, I was here. You can get this workflow going, even in inspect mode. Just being able to visualize the animation in terms of key frames, I hope, is quite useful for people. But there is the sort of true mode, unlockable. It's unlockable for $49 forever at the moment. Normally it's a subscription. For learning with Jason, it's $49 forever. And I added you anyway. So if you click on login, this should work. Yeah, if we authorize Motion One. I didn't take any of your personal data. Brilliant. Okay. So now that's unlocked. Now you have the full thing. So you can -- yeah, you can do anything. You can change the easing curve. You can change the clip path. Oh, hi, Yanir. I know you from Twitter. If Motion One ends up in Framer Motion, which I'm actively working towards, then this or something like it at some point -- like, this sort of experience will end up working with Framer Motion at some point. I don't know if it will be this or if we'll do something with Framer, but that's the plan. So at the moment, I see if you made the DevTools panel just a bit higher, you can see that we've got --

JASON: Oh, I've got more.

MATT: Yeah, it just got cut off. You can do things like delete the key frame, or you can even add. I can't draw on this screen, can I?

JASON: So I can start messing with these a little bit.

MATT: Yeah, exactly. But you can also add new key frames. You can see there's this little plus icon on the div2. Here we can add, say, X. Then if you click anywhere within this -- oh, that's upsetting. Oh, that's upsetting. A crasher.

JASON: Okay. Try it again.

MATT: I think you need to close DevTools. It's your one fear, coming on a show like this.

JASON: Okay. So we've got our animation.

MATT: I suspect the reproduction path is going to be exactly the same. Okay. Fingers crossed. Ah, well, at least I know exactly where that bug is.

JASON: (Laughter)

MATT: The problem with DevTools is it is incredibly difficult to get a good test going because it has to be -- like, I haven't really figured out a good way to load it. So if anyone has any expertise in this. I haven't found a great way to load it into a Jest or Cypress because it's a DevTools thing. Let's try field. Okay, that's weird.

JASON: Doesn't like any of them.

MATT: By the end of tomorrow, you'll be able to add new values to the thing. It's a shame because that's probably my favorite feature. It's weird. Anyway, I won't think too deeply on it. Rename existing values is there. If you want to swap X for Y, you just change the name for it. As you can see here, you can change the --

JASON: Oh, yeah, so you can really quickly start kind of putting some stuff together here and figuring out, oh, if I do it this way, then this happens. Just starting to, like, bounce it around a little bit. That's fun. Ridiculous.

MATT: Yeah, exactly. And so the nice thing is if you now -- you can click in the bottom left. We have this export button. What this isn't is the code that you wrote back at you. We've generated this kind of from scratch because we only get some values and stuff. But what it does do is let you copy some of the code. You've changed the easing or the key frames, as you can see there. You can just come in here, fish it out, and stick it back into your code.

JASON: Right. So like I added this value here.

MATT: Yeah, exactly. Which is nice. And this animation was made in Motion One. So it's defaulted to the Motion One tab. But you can do things like go to CSS animation. This is the same animation but in CSS animation syntax. And likewise, you have the CSS transition. Something to point out here with CSS animations and transitions. Obviously, CSS transitions can't do multiple key frames. So you can come in here, and you can get an animation to the final key frame because this is not a key frame animation. You know, it won't look exactly the same. But the other thing to point out is while you're seeing some of these CSS variables, Motion One -- so WAAPI, CSS, none of them can animate independent transforms. So you can animate the transform string as a whole, but you can't animate it -- so very modern browsers will support scale, for instance. You could animate translate X and Y as one property, and you could animate scale as another property. But if you want to animate them with different easing curves or you want one to start at a different time, you can't do that in most browsers. You can do it in some. What you can't do in any browser, and there's no plans for this to change, is animate individual axes independently. So if you want to animate translate, it has to be X and Y together. If you want to animate scale, it has to be X and Y together. Whereas in Motion One, we use -- it has this little system in the background where it will automatically animate the CSS variables and construct a transform string that will -- so you're able to animate each of these individually. This is invaluable when it comes to something like Framer Motion or whatever it is. Most often, it's like the in view and hover animation. So you're scrolling through, and it enlarges when it pops into view. So that tends to be when you use those. This converts that kind of system into CSS. So if you scroll it to the very top of this little window here -- oh, you were already there. We have this thing called app property. What I'm going to do, I think, as a future feature, is put a little warning sign when we're doing something like this. What this is, is a brand new CSS Houdini API that allows you to register CSS variables and give them a type. So this one is a number. Now Chrome knows how to animate that with WAAPI. It could be anything. You can do things like color and stuff. We haven't needed to do anything like that here. But you can do stuff like that here. You can see how this is all sort of coming together there.

JASON: Yeah, yeah, yeah. Okay. This is really cool. We need to do a whole episode on Houdini because that's a mystery to me. But it's extremely cool we were able to mess around with this, add in some different pieces, and you kind of get some good animation chaos here. Very, very quickly. And I didn't have to do anything, right. I just kind of clicked on some stuff and decided I was going to play around with it. I can make things bigger, smaller, or whatever. You just immediately -- this is intuitive. I can understand what I'm doing, what I'm trying. Feels like that's a good -- it feels good.

MATT: I'm glad to hear it. That's the sort of -- I feel like for too long, we're a bit like in the browser, we bump out, fiddle with the code editor, come back. It's this ping-pong. With CSS, a lot of times we don't do that ping-pong. We edit it live in the browser. Then when we're happy, we copy the things we changed, and paste it back, which I won't say it an ideal workflow either. That feedback loop is much tighter than what we do for animations. So I'm kind of trying to get back to that experience and trying to get back some of that flash playfulness as well. Bring back some of that.

JASON: You know, that really is -- like, I don't miss a lot of things about the era of the internet where Flash was reigning supreme. I didn't like when every website was a mystery. I didn't like when everything played music when you opened it. But oh, man, I miss Flash games. I miss the creativity that you would see on sites where their homepage was just a fun little animated thing. We're seeing some of that come back, and I'm really happy to see it. But yeah, APIs like this are what get us there. At the moment, we're just not -- it's just a lot of work. And the cross-browser inconsistency and having everybody's computer try to take off into orbit whenever you spin up your animations because they're so JavaScript heavy and non-performant. I want that whimsy back on the internet. I want us to start experimenting. I see Jay is in the chat. I imagine this is up Jay's alley. (Laughter). I just noticed all the eyeballs and the Biblically accurate Twitch chat. This is very cool. I feel like we could sit in here and tweak on this, but did you want to try something? Like maybe we could build something and see what we get to.

MATT: Yeah, for sure. For sure. So I don't know what your preferred work flow is, but whatever it is, let's do that.

JASON: I usually just work in something like Vite. Is there a specific library we should do?

MATT: The other thing is we don't have to work in -- this could be CSS. If you're happy with CSS motion and transitions, we could use those.

JASON: Okay. Let's do npm -- what is it -- create. Is this right? Yes. Okay. And we're going to do motion dev tools. Yeah. Should I use Vanilla or React? What do you think?

MATT: You could use Vue.

JASON: Okay, but you're going to teach me a lot of Vue.

MATT: Oh, no, I don't know anything about Vue. I'm happy in React, in that case.

JASON: I see you in the chat, Matt, but I'm going without TypeScript. Sorry. (Laughter). Sorry, everyone. I get -- (laughter). Just torturing Matt, that's my new hobby. Let's open this up so we can see what's going on. And there we go. I don't -- what? Why does it want me to install Docker? Not today. So we've got a really basic site here. Looks like there is some defaults set. And a plain old div. And work from there. So I'll just do one of these.

MATT: I've never used Vite before. Feels like I'm missing out on something here.

JASON: I need to update my CLI because the Vite target port changed. It went from being 3000 before. Older versions are still looking for the original Vite setup. So let's do all this. We'll get Netlify dev going. And it's still using the wrong version. All right. We're just going to run npm run dev. I'm not going to debug Netlify CLI and why my system is not installing properly. So here we go. We've got this nice, fast Vite setup. We've lost Matt.

MATT: I can't get over the crasher. Straight for the nearest exit. Can't win with these windows. So this is interesting because this already has the React logo animated. I wonder what happens if we inspect the page.

JASON: Yeah, let's try. So I'm going to go over here. We'll open up Motion, and I'm going to make this bigger. It looks like this is done with --

MATT: So if you refresh the page, I believe.

JASON: There it is.

MATT: Yeah, so that's the -- so we can see that -- oh, this isn't my day.

JASON: (Laughter). Refresh the page. We've got our image. We've got our transform. And it doesn't like that one.

MATT: That's a shame. I wonder what's going on. And it's funny because I was thinking --

JASON: And it definitely could be I'm in Edge and not Chrome. Oh, boy. I haven't even installed Chrome. Okay. We're rolling.

MATT: That's a fair point to make. It's like Chrome only, and I was curious to see how well it ran in edge.

JASON: And we're learning. (Laughter)

MATT: Yeah. Well you know, it keeps it interesting. You've got to keep on your toes. What happens if you just scroll over to the right? Let me just check something on my end. That's a 20-second animation.

JASON: Yeah, that makes sense. So it does one rotation every 20 seconds. I get it. And if I wanted to make that absurd, we could do, like, triple the speed. And the easing curve is -- I've got to give a shout out as well to Leva. I can't pronounce the people who make it. It's the same team who makes React Springs. Oh, yeah, go for it.

JASON: Is it like Bostonian? Wait, what did I do? I went Australian. I don't know why.

MATT: Have you watched "30 Rock"?

JASON: I have.

MATT: There's a Bostonian accent on that. Julianne Moore, perhaps? It's quite upsetting. And I feel like your Bostonian accent just now -- I mean.

JASON: I don't even think it was remotely close. Not even the right continent, everyone. So please don't clip that. I don't want that -- we're going to edit that out of the final episode. So, okay. I think it is letting me edit, but I don't think it's actually working. Let me see if I can shorten this up and make it go faster.

MATT: In the industry, we call that a bug. No, I don't know. Let's do a homegrown one. I think that is odd. I haven't seen it before.

JASON: I'm going to delete most of this. I'm going to leave that bit. (Laughter). Now it works.

MATT: There she go.

JASON: Okay. I think I might know what's going on. I think Vite is doing something with the CSS so when we make edits, it's not getting picked up until we do hot-module reloading. But that's okay. Now that we know that, we can account for that. So when I'm in here, I need to also -- are you, like -- there you go. Now there's no animation. And I can go into my app.jsx. Maybe we just clean this all up for now and say -- now we've got one of these, and we can start doing our actual setup. So we want to animate something. What's a good thing to animate?

MATT: Well, is this stupid? We could do the -- people love per letter. It's kind of interesting. People always love a per-letter text. So we could make this wave, basically.

JASON: Yeah, yeah, yeah. Okay. Let's go in here. We'll do one of these. Font size, we'll make it a little bigger. We'll say, like, 2rem. Yeah, let's give it a font weight of -- make it nice and beefy. Do a text transform of up case. All right. That's looking okay. I'm going to close this so I can make this smaller too. All right. How should I go about doing a per letter?

MATT: So how you should do it and how we're going to do it are probably slightly different. How you should do it is probably grab a library. So the first thing to do -- and the reason why I suggested this is because I seem to always get asked it. Yeah, it's kind of interesting. I wonder if part of the reason people run into issues with this is that -- so if you wrap each -- so the first thing we have to do is to make a letter animatable, we have to wrap it in its own element. So the first thing to do is to wrap each one in a span. So it's a good thing we didn't choose some paragraph here.

MATT: Well, that was neat. I don't think I've seen that before. How did you get them to just go down one per line?

JASON: I was hitting alt-click the whole way. But yeah, having a short word was definitely the move. So then that means I can make these display -- what do we want -- inline block.

MATT: Yeah. Maybe, yeah. They have to be at least inline block, yeah.

JASON: But they need to have a layout because some of the properties aren't animatable, right?

MATT: Yeah, exactly. I'm glad you pointed it out.

JASON: I feel like most of this show is me taking a pop quiz, and I'm so happy when I know a thing.

MATT: Yeah, yeah, yeah.

JASON: So many times it's just me taking a wild guess. You can just see the expert is looking at me like, oh, you poor, silly fool. (Laughter)

MATT: No, no, no. It comes up a lot. This isn't working. This animation isn't working. Not almost always, but a lot of the time, it's a span or another display inline element, and transforms don't apply. I've been tripped up by this, and I know that it happens. So I can only -- if you don't know it happens, you think you're going mad, basically. So display inline. That is essentially how I've debugged this before. You're in the pit of despair and you're trying everything. Make if I make it position absolute. Make it red. Will that work?

JASON: Border one, solid pixel red. That's my trustiest of debugging tools.

MATT: Yeah, exactly. Okay. So for a wavy animation, I guess the easiest thing here is animation:wave 2 seconds. I think. I'm not such a JavaScript animator. I don't really know the full syntax here. This looks right.

JASON: It's like infinite. That'll give us -- that'll loop it. Now we don't have an animation, but we make one with keyframes wave then what do we do, zero percent and 100%?

MATT: Yes. Well, if we -- yeah.

JASON: It'll at least get us started. So we can do -- what's the right move here? Do we want to start it at, like, transform, and it could be like translate Y in pixels.

MATT: Someone said just 50%.

JASON: Cool, yeah. Let's go.

MATT: I like the responsiveness of this.

JASON: Then we'll bring it back to zero. Theoretically, look at it go. Okay. So that's a little slow. Let's do 200 milliseconds. Oh, too fast, too fast. That's a little better. I'm going to slow it back down so we're not getting the jiggle that's a little jarring. So we'll do this nice and slow and speed it up once we figure out what we want. So the next thing then is we need to offset this by its index, right? So zero, one, two, three, four, five, six.

MATT: Yeah, is it span nth child one, nth child two?

JASON: Yeah, is there -- hmm. Jay is in here. Do you know, is there a way in CSS to use the Nth child index in the CSS? Or do we need to set this as a variable? We'll see. We'll see what Jay comes back with. While we're waiting, I'm going to do a -- so here's what we can do. We can do an offset zero. Then what we really need is like an animation offset of -- we'll do like offset times 50 milliseconds. I believe what that should do, assuming I'm using all of this correctly s right now it's not going to do anything. Everything stays the same. But if we go into one of these, Nth child one, then we'll do an offset of two. That should mean -- that means nothing. Animation delay, no offset. See what happened, y'all?

MATT: That is right, yeah.

JASON: So it's a little goofy. But it's doing the thing. Splitting will do that for us. That would be ideal, but because we don't have that, we're going to instead just hit this with a hammer. So we've got six letters, seven letters. So one, two, three, four, five, six. Oh, no. What am I doing? One, two, three, four, five, six. Then we'll just do one of these. Nope.

MATT: You know the time it took you to come up with a clever solution, you could have just done the copy/paste solution.

JASON: Absolutely could have. And then this one? Is it a zero? Let's try zero and see what happens. So this is good. Now what we need to do is we probably want it to be, like -- sorry, go ahead.

MATT: Oh, so I feel like two of these -- so if you press record now and refresh.

JASON: Save this, refresh. Let's record.

MATT: So if you look at animation two -- oh, by the way, I figured out what this bug was. It's a me problem. I've integrated a library problem, but it's a first key frame problem.

JASON: So if I use the second, we're fine.

MATT: This is why when we added a new value, the first one (indiscernible). So I'll fix this imminently. So on the graph, we should be able to see if they're stacked correctly or as we want them.

JASON: So I was just informed that Nth child starts at one. I'm going to move this back. That should give us -- interesting how that just happened. The hot module reloading messing with all of it.

MATT: Yeah, so once you're inspecting an animation, and if it tries to start again, you're inspecting it. So it doesn't necessarily work correctly.

JASON: That's okay. In this particular case, we know what we're doing. So we'll just refresh whenever we make a change. It's a short animation, so that should be okay. So the next piece is figuring out -- what I would like for it to do is each one to kind of go woop. We want that. So that means we need to start at zero. Then like a fast ease up and a slower ease down to make it look like it kind of woof. Right? You're going to have to talk me through this.

MATT: So you want a fast up.

JASON: I think we probably want it to like swing up a little faster and then kind of look like -- like if you take a towel and flip the towel out, it goes up fast, and it kind of drifts down at the end.

MATT: In that case, I reckon we probably want a 50% key frame.

JASON: Okay.

MATT: Where the transform is --

JASON: Wait, I want to do it up here. I want to do it in the tool. Okay. So here's my 50%. Okay. Then we want like an ease in. Then we want this one to be like -- translate back to zero.

MATT: This is the problem. Yeah, I really want that first key frame to be zero.

JASON: Okay. I'm going to make the first key frame zero. That way we can mess with this a little more without everything exploding. Let me refresh that one more time.

MATT: This is something I'm confused about. If you go to animation two and three here in the tabs, this is all of our animations. I'm thinking something to do with the scheduling of these animations because they're delayed one after another by how much --

JASON: Oh.

MATT: Yeah, I'm a little confused, to be honest. Because we do handle delay, and you can edit it. So I'm wondering if we've hit some sort of edge case where CSS animation -- animations defined in CSS animations, the delay is not coming through.

JASON: They're here.

MATT: I've seen this before. So depending on what frame -- so we grouped these animations together based on our own arbitrary -- I think a two-frame window. Any animations that start in that two-frame window is considered the same animation. And I'm wondering if the delay here with CSS animations, for whatever reason, is starting the animations when the delay has finished, not like to start. Usually you get the animation, you get a delay period, and that's considered kind of part of the animation, I believe. Which is why in the timeline, they're all starting from the same point. This is my theory. But yeah, we see here the delay isn't coming through.

JASON: Hmm, okay. Yeah, well, the delay would be not on the key frames but rather on the -- yep.

MATT: Calc offset shouldn't be a problem because I think we used the -- if you made that 100 milliseconds for everything, I'm just curious as to what happens there. Sorry, they'd have to all be the same. Now this is learning with -- you're teaching me.

JASON: Yeah, let's try. Let's see what happens. We're going to record. I'm loading. And now they've all shown up. So the delay did work as expected. And if I come in here and I make another one, we're going to do 50%. Let's skip back and try again. It doesn't like my key frame.

MATT: Yeah, it's not you. I feel like this is a -- like you're saying about the hot reloading. I've never tried it. I'm wondering if I should.

JASON: Yeah, I wonder if it's something in the way this is -- wait, what just happened there?

MATT: I haven't checked it out in Firefox, but I should. I'm having trouble. Like, the delay seems to be easy enough because you put the first key frame into the animation by that amount. But negative delays are valid, and we don't visualize that well in the tool at the moment. So yeah, negative stagger would be really good.

JASON: A negative stagger. Okay. Negative stagger like this?

MATT: Oh, no. I was just responding to the chat. Well, it's a shame the DevTools didn't reflect this, but the animation is looking better. It's in rubber-ducking mode at the moment.

JASON: All right. It does five little wags, right. This is fun. Okay. So we can probably do one of these. Or no, let's do one of these. And it's 700 milliseconds. So we'll slow down the delay a little bit.

MATT: And just curious, if you click that middle key frame there --

JASON: And I want to change it.

MATT: Okay. So now it works. I'm curious as to what's going on. That's bizarre.

JASON: That's fun. So we probably actually want to pull this up, right. Yeah, okay. So that's kind of pulling everything together here. We get our sort of whack-a-do one of these. Make it kind of aggressive. Then what we can do is sort of pull this all together to be a little more -- yeah, that should be fun. If I export this, I get -- this is my cubic. So I'm going to grab this one. And drop it here?

MATT: Yes.

JASON: Oh, this is me screwing up here. That's why that didn't work.

MATT: This should work, I believe.

JASON: Look at that. We got some basic pieces going on here. So if I reload again, we've got all these. Now if I want to go in, it crashes. I love CSS. Chat, have I ever told you that I love CSS? Have you ever noticed? What's up, Alex? Thank you for the raid. What's up, everybody? Yeah, this is fun. Okay. So you want to try anything else?

MATT: I wouldn't mind showing you -- this is slightly adjacent to the DevTools, but a quick introduction to -- and I can send you the -- I'd just like to show you at least the scroll animations.

JASON: Yeah. Yeah, yeah, yeah.

MATT: So this is a new scroll animations API in Motion One. It's made its way into Framer Motion as well within a hook. So let me just dig this out for you.

JASON: I assume I'm installing Motion.

MATT: Yeah. Sorry. I've switched.

JASON: Yeah, I've got it installed so I'm readied to use it.

MATT: Brilliant.

JASON: I'll probably just drop it down below.

MATT: Yeah, why mess with perfection. You don't want to get rid of --

JASON: That's what I always say. Call this waggle text because that's what it is in my heart. Then this one will be -- what do you call this feature?

MATT: I just call it scroll. Scroll-linked animations.

JASON: We'll give it a scroll. Then I'll end up making this one a little bigger so we can tag on scroll. Then, yeah, what do we want to build in here?

MATT: I was thinking just something that makes images fade in when they scroll into view.

JASON: Okay. Something that makes images fade in. So we would want a list of images. We can go to the old Unsplash, and today is hot outside. So I'm going to get pictures of ice cream. Beauty. Look at these beautiful photos. So we're going to get this one. You don't get alt text, do you? Forgive me, chat, I'm going to use the same alt text for everything. You don't need to tell people it's a photo. It's ice cream. Then I'm going to save that. I'm going to make two, three, four, five, six. Let's get a few more photos of ice cream. So here's -- did I lose my search? I did. So one more. And drop this one up here. That one looks delicious. Collapse these ones down that we've already done. Delicious. I wasn't thinking about getting ice cream today, and I think I've changed my own mind. Why show me an empty cone? I love a waffle cone as much as the next person, but come on now. We'll get this one. You know what, I'm going to call that good. That's enough. I'm going to delete these other two. So now, if we come out here and we look, we have all of these photos. They're way too big. So I'm going to do a little bit of work here. This one is going to be waggle text. That's going to be a min height of 100. Down here we can do the same sort of thing. We're going to get control. I guess that part actually doesn't matter. All we really need is this, where we can do the -- the width is going to be 90. We'll do display block. Probably like a margin of 1rem auto. There we go.

MATT: Cool.

JASON: Okay. I'm ready.

MATT: Sweet, all right. So for this -- oh, we're in React, aren't we? In the app.jsx, we can import, animate, and scroll from motion. Now in a use effect, if we import -- yeah, I guess use effect is best. With an empty array. We're just going to do this on load, I think.

JASON: Oh, stop. Okay.

MATT: Now we can just do document.query selector.

JASON: Oh, all. Image. Is that correct?

MATT: Yeah, that's right. And now we want to iterate over that because we want to do this once for every image. So for each image. So the scroll function can basically accept a Motion One animation or any function basically. So what we're about to do, we can do for Motion One animations but also WAAPI or I had it scrubbing a video the other day. Things like this. Anything you can plug a zero to one into basically, we can use this for. For now, what we want to do is let's make a scroll function. And so we want to pass a Motion One animation. It's the first argument. At the moment, it's object. But if you remove the object and replace it with an animate function, what we want to animate, our image. So just type in image. Then comma. We want to fade this in, when it comes into view, basically. So if you open an object -- now, in here, we can do basically anything. So scale X. I don't know. For now, let's start with opacity. The animation is a scroll-linked animation. With a time-based animation, we might want to do something like opacity one, and we'd set the zero in CSS or something. We want these two key frames we can go between. We can put as many key frames as we want in, and it will interpolate through that. But it's the second argument to scroll. We want an object that has -- we're going to give it two options, basically. One, we're going to give it target. And this is also the image because what we want to do is track the image's progress as it sort of moves through the viewport. We can give it other containers if this is in another scrollable element. Or you can give it a different target to animate a progress circle SVG. You could do like the scroll container thing. What people do where you can kind of see how far down the page you've scrolled by the bar getting wider.

MATT: Yeah, exactly. Yeah. Now that I've said this out loud, I think that would have been a much easier thing to start with. But I can show you that in a sec. So now we want to -- actually, if you go to the -- if we check that out, we can see what it's doing already.

JASON: Sure, okay. So we're here.

MATT: It might not work very well, but I'm curious.

JASON: Text is waggling. Here we go. Oh, boop.

MATT: I see. Yeah, so what this is doing, by default it seems to be using the first key frame for when the image hits the top of the screen and the last key frame. When the target is hitting the bottom of the screen and between that is going between zero and one. Really, I feel like we want it to start animating as soon as it enters the viewport. So if you give it a new option called offset, and this is also an array. So we want two key frames. You can give it more. It will divide that. So say you gave it four, it will divide that into like, 0.25, 0.5. That can start mapping multiple key frames.

JASON: If I were to do four options here and four entries here, would it map those one to one?

MATT: Yeah, yeah. Exactly.

JASON: Gotcha. Okay.

MATT: Just to the chat, this isn't an intersection observer under the high school. This is just scroll events, but it's written in such a way that when the scroll-linked animations API gets better -- not better, but more defined or more stable and browsers start supporting it, when we use it with the animate function like we just have here, we'll be able to swap it out for native scroll events. Sorry, native scroll timeline under the hood. Yeah, so you get all that thread performance and stuff. But we have intersection observer better for triggering things. So when things enter the viewport, it triggers things. We have a function for that, but it's called in view. It's an easier way to use intersection observer. So you mentioned you used scroll trigger earlier.

JASON: Yeah, I've used scroll trigger.

MATT: Okay, cool. So this should work very similar. If you make a string, we're saying when the start of the target, which is the image -- so we work on an axis-agnostic way. We don't say top and bottom or left and right. Everything is start and end. So we're saying the start of the target on the axis that we're tracking, which is Y, when it meets the bottom of the container, which is the viewport, so here you just write end. Then we want a second key frame, which will be, I don't know, when the start of the container --

JASON: Hits the center maybe?

MATT: Yeah. So this should now fade in.

JASON: Yeah, so it immediately starts fading in. I like that. It's fully faded in by the time we get midway up the screen. That feels a little -- yeah, this feels a little better. It feels a little more kind of native to what we're doing, which is great. That was nice and easy. I like that.

MATT: Oh, cool. Yeah. And so we can do things like the scroll bar is even simpler. We can track a div in there that's like position fixed. And we just wouldn't even need the options. We'd just pass an animate function that animates the progress bar to scale X. And from zero to one. And we'd also -- because all of the defaults -- if we're on the window, it will be the scrollable area. So like the whole page basically. So that's how the defaults work quite well.

JASON: Got it, got it. Yeah, so this is really exciting stuff. This is all documented in the Motion One site, I'm assuming.

MATT: Yeah, yeah, yeah. So for the Motion DevTools, I'm going to fix this key frame bug. A little better than what we saw tonight. Motion.dev/tools for the Motion DevTools. And we have the scroll function. It's best just to go to motion.dev and read the docs. But it's like /dom/scroll. I'd probably to do a, what do you call it, London page for scroll at some point. I want top show off all the different example. But yeah, this has a bunch of examples on it that are all code sandbox. You can just fork those, and they're looking pretty good. Oh, and I should as well mention that -- yeah, this is what I was talking about. What do you call it? The scroll X, like that progress bar at the bottom there. You can see we're doing parallax as well, which is pretty simple with this API.

JASON: Yeah, and it's locking to a place, which I really like. So unfortunately, we are out of time. So are there any final links that you want to share with folks, if they want to learn more, other than the ones we just shared?

MATT: No, that's it. Motion.dev. If you're a React user and like the scroll animations, this is one more thing. Go to framer.com/motion. Through that path, you will find the use scroll hook. It's a new hook. It's built on the functions you just saw. But it might play into if you're already a Framer Motion user. It will work with that more fluidly.

JASON: Folks are asking if you stream.

MATT: I don't, no. I could. I don't know.

JASON: I'll tell you what, everybody go follow Matt on Twitter. You'll be the first to know if Matt does indeed start streaming. This show, like every show, has been live captioned. We've had Rachel with us here all day today. Thank you so much from White Coat Captioning. That's made possible through the support of our sponsors, Netlify, Nx, and New Relic, all kicking in to make this show more accessible to more people, which I appreciate very much. While you're checking out things on the show, check out the schedule. We've got some great stuff coming up. We're going to do some visual pageability with Plasmic. We're going to do Rust, auth zero actions. A bunch of things I've been too lazy to put on the site. If you want someone on the show, give them a shout on Twitter. Tag me. Let me know who you want to see on Learn With Jason. I'm always looking to learn. Matt, thank you so much for spending some time with us today. This was a lot of fun. I think people are going to have a lot of fun with some animations and everything. With that being said, I think we're going to call this one a success. I'm going to go find somebody to raid, chat. And y'all stay frosty out there. Matt, thanks for spending some time with us.

MATT: Thank you so much for having me. It's been a blast.

JASON: Take care, y'all.

Learn With Jason is made possible by our sponsors: