 Welcome to another episode of GUI challenges where I build interfaces my way and then I challenge you to do it your way Because that's our creative minds combined We're gonna find multiple ways to solve these interfaces and expand the diversity of our skills and in today's GUI challenge We're building a card stack. How would you do this stack? How would you make it do these animations? Do you see a little bit of what we're gonna be doing today? We're animating transform origin and making some pretty sweet effects All right, so for a quick overview of what's going on. We've got a group of cards and They're all in one little area They're piling on top of each other and that's being done with grid now You can see I have a hover effect on here, too So when I hover they protrude up and notice that they're not just moving physically up there They're shooting up from where their transform origin is and that's critical We're gonna we're gonna kind of go over where I was originally using individual transforms But I couldn't get this effect with them and so we'll debug that But okay, so we have a stack with grid all of the interactions with this form over here on the left in these field sets Is using has so when one of these is checked I go and update the position of all these to this transform origin and watch them all sort of animate They each have their own little bit of rotation. So here if I go back to the center We have some that are rotating counterclockwise and some that are rotating clockwise and they're all Rotating based off of what I'm calling here like a a scalar or some there's a multiplication happening So here's multiplied by zero here's multiplied by one and then as we continue adding this scalar effect We can see them fan out in different directions and that's just kind of cool on itself I kind of like that reveal it just looks really nice Anyway, that's what's happening here And so this scalar is just essentially setting I mean I call it a gap But it's kind of because it kind of looks like a gap that's affecting the rotation on these particular elements Okay, so we have has that's looking at the values of these forms and assigning some kind of states for these transitions We have grid which is doing the overarching kind of grid here And then we have some transforms using custom properties We're going to go over all that today as well as dive into some of the bugs And let's of course go check it out in the debugging corner first because there's kind of a surprise over there That I want to share with you. So let's go check that out. Here's the debugging corner We've light things on top and iOS, which I think just looks kind of nice Let's let's pick some cool values for this here How about that one? Yeah, that looks nice. It looks like a little fan like a key chain fan of cards. That's cool Pick this one is bottom center Sure, I mean even though I prefer this kind of center where it's got a really far out Value we'll talk about that here. Here it is working on iOS cool Here, let's just bump up that gap. Yeah, that's fun Bottom left sure bump up the gap. Everything's looking good in here So has is working across all these different platforms now over here. We have Firefox Looking like it supports has so here. I'll just change a value. Oh, but it didn't change Well, look if I reload the page then it picks it up So there's an experimental implementation of has in Firefox. It's just sort of not Live like if the values change after page loads, they don't they don't update So here I can reload the page and see the effects of has but it's not as interactive Which is fine and then this one's powered by JavaScript and it's just kind of writing values And so you can see that's working great, but interesting, right? So Firefox has an experimental. I went to about config Proceeded with caution. I searched has and in here I saw look at this layout CSS has selector enabled I enabled that and that's what gave me this feature here where I can reload or I can reload it and see it in action So anyway once has is available on Firefox stable This demo will work flawlessly, but for now it's a little clunky in Firefox But that's okay. The interaction model here with using has was just kind of fun We could easily write some JavaScript and make this cross browser, but I just thought it was fun use I like has I want to use has so anyway That was the feature here is working across all the browsers look sweet Now, let's go dive in and inspect how this was all accomplished over in Chrome All right It is time to dig into the grid layout the transforms and the use of has that is powering this thing So I'm gonna hit command option I to bring up a dev tools and let's look at this first grid on the body So we have two equal columns created by grid template columns repeat to 1fr It also has place items center, which is the same thing as a line items center and justify items center We can see that being effective here. Well, let's drop this gap down Well, yeah, zero is fine Just so we can see the layout these items are vertically and horizontally center rates We have aligned them to the center and then we've justified them into the center over here We've aligned them in center, but hey, how come the justification isn't there? Well, if we go look at the card stack, it's said to justify itself to start and the reason I did that was well Here if we fan these back out again, and if we don't do this see how they're like immediately off-screen We can go off-screen really easy. It's like seeing like top right or if we fan these out more just kind of I didn't think that looked as good as if we tuck it in a little bit And now we get to see more of these items and it just ultimately feels a little bit more attached to our content here So that was cool. We also have a form here with a grid So let's turn on this grid and check out the styles here. We have display grid with a gap, right? Here's our gap and we have justify items start now This is something I really like to add to grid and flex layouts so that each item can have its own width So if we turn this off See how this section and this section were stretched to fit it also kind of oddly Changed the size of these elements But if I said justify items to start then their own sizing the length of this label is determining the width of this field Set same thing here with this this slider is determining the width of this Gap field set and I just think that looks really nice and so we have justify items start there for that Let's look inside of here each of these field sets these fields have a cool trick So that's just said to display grid with a gap notice There's no template yet if we look at the label here because look we have a we have like two columns But these are all just a bunch of items in here. So if I take out grid column 2 This is what that grid layout does by default to this just stack of content But by setting the grid column to 2 on the label. I'm essentially telling this parent grid I need a column I need a second column and it goes okay Well, here's a second column and it puts all the labels inside of there And then it looks at all the inputs and go well you haven't been assigned anything So you're just gonna go into column one will auto place you into column one every label will be placed in column 2 And then we get this really nice layout and that was all it took was just assigning that label into the second one Which comes in especially nice here because if we look down here at this item, it doesn't have a label It's just got the legend here as part of the field set And if we were to so here if I take out grid column 2 if I was to go into the parent Layout here for field set and create some grid template columns grid template columns and say like Auto 1fr which should give us a pretty similar result. See how we get a very very similar result We have an auto so the first column is being set by the contents. They're all the same So it's just this small fit and then this next one is going to be 1fr It's consuming the rest of the space and then these items are all going to get to set to that length But look down here it created a second column even though there's nothing to go inside of it And that's because we defined grid template columns. We said there's two columns But that's just not the case all the time So by switching back to this one where there's a dynamic set of columns created just for these labels This particular case down here doesn't get an extra column made So kind of a cool little trick there to use with grid All right, so let's go on to our card stack and check this one out if I hit grid. We'll get our what is this look at this We got a cool little labeled Layout that says GUI challenges all's a little Easter egg I put in there for everybody You're probably a little tired of hearing me talk about this stack layout That I do with grid all the time because I I'm avoiding positioning elements absolutely But I am getting them all to fill the same space here Let's take out the gap let them all sit on the same spot and check out how this was accomplished So I have display grid of course we have grid This is the template being defined for rows and columns at the same time the rows the first start of the row The like line name here you could see it right here. This row is called GUI and it's taking up one FR So it's just going to kind of fit and fill the space that's being given Then we have a slash because we're going to define our columns and this column name is going to be started as Challenges and its size is min 50 v min or 40 characters So we're kind of saying don't go bigger than 40 characters But allow yourself to be flexible at half of the viewport space and if I drop this down We can see that this column is defining the size of this column and then these cards each of these cards has an aspect ratio set Where's the aspect ratio right here to ratio portrait, which is the same thing as look up I hover you can see it there three by four Three by four and that's why these elements are consuming and being that large is they're filling the column that they're given And they're of an aspect ratio So both of those things combined make them fit into the allocated grid space that they're being given and Maintaining a ratio of a card shape so kind of cool come back to this card parent layout and Again, just remember that these are one row one column one row one column And then each of these is being assigned the grid area of GUI challenges So it's saying you should be on the row that starts with the name GUI And you should be in the columns starts with the name challenges and sure enough that puts them all in the same row and the same Column all in the same single cell and they stack on top of each other very naturally and at this point We can begin doing our transforms that starts to rotate them out in different directions And so worth noting here that some go counterclockwise and some go clockwise And we'll go look at how that's calculated here in just a second Cool So that is the grid layout for that and that kind of concludes all of the different grids Although one of the things I really liked about this was like if you set this up And you go into the layout here and you kind of extend the grid lines You can start to see some really healthy relationships that happen between your alignment And I also think it just looks neat plus you can change these colors and pick something way ratter I care. Let's collect hot pink and this one will do like a super vibrant lime green Yeah, look at that. Now it's on the theme. Wait, are this one is yellow here? Yeah, let's change this one to Cyan great, right now. We have like some really neat looking overlays You can also come in here and easily turn those off the grid tab tools are really nice Make sure you have show area names and show line names on if you want to see the line names here So these are the line names There's no area names to be shown and then I've extended the grid lines So just kind of cool tips and tricks with grid grid is super rad. I'm very pumped on it Okay, so let's check out the next part, which is how are all these sort of transforms being applied? So let's inspect a card not this card because it's kind of not doing anything interesting Let's check out this card this one that's kind of spun out all the way on the left and We can see our selector for it, right? Okay, so we have HTML has Hashtags so it's an ID of an element. This is one of our radio inputs is called mode bottom center if it's checked Go find the card stack and each card set their transform origin to bottom center So that's how all of these are being transitioned right now is we're just transitioning one property on every single card Called transform origin to the bottom center, right? So I could pop in here and edit this if I wanted to be like top center. Oh, that was kind of cool Just top left. Oh Right. Oh Here, let's increase the gap That is cool. So then here if I come in here and go left. Oh That is awesome. If I delete it it just goes somewhere. That's sweet top bottom Center bottom right right bottom left Top left Top, right. Okay. Okay. You can basically see here. What we're supposed to be bottom center bottom So you can see how I came up with these different radios and how I was having fun is I initially set this up so the transform origin was going to be the thing that kind of pivots all of these and I just had a bunch of fun was like wow This is this is way more exciting than just a card stack animating this card stack using the transform origin is really cool And that's when I came up with here. We'll decrease this gap a little bit These are the built-in transform origin So if I use the keyboard here, I can kind of just move through here So we've got bottom center bottom left top left top right bottom right And I like how it just sort of shifts amongst all the corners here. It's good stuff And then since this radio group has the same name as this radio group even though it's two separate field sets You can see that they all maintain they can only have one selected and so it can either be these custom ones Which kind of show how to do additional Kind of perspective origins that extend beyond just inside of the box So what's nice about these ones is they all stay inside of the box But I really like how this fans out which is a lot closer to how it would fan out in your hands Because the palm of your hand is essentially the transform origin You can imagine like the palm of your hand is right here And then you fan them out from there and it gets a much more natural looking fan out than if you just do bottom center See how this one you can see here's the perspective origin or the transform origin right here Whereas this one says it's center horizontally But 200 off-screen outside of the box and it gives us this really nice arcing effect Which is kind of cool and then here's some other custom ones to do so this one is negative 25 negative 25 So it's over here and up here and kind of gives them this nice as opposed to like top left Which again, they're really tight on the corner Which can be cool like if you want this keychain effect But if you wanted the effect of like in somebody's hand or it you know Something's holding it up here You can set that transform origin off into the distance and that was just a really fun effect And if you combine that with all the rotations, so let's look at the rotation here We have are being calculated against our scalars So this is our scaler here as this changes you can see our scaler here being updated So it's set to nine there it is at 14 here does it for let's set it to two So the math is nice and easy for us to do in our minds go back to a card And we'll look at what's happening here So this first card is being set to the scaler times or five so five is the default But right now scaler is two so two times two is four times one degrees can be four Degrees times negative one is going to put it negative four degrees. So let's check out this one This is the same one, but look it's not multiplied by negative one So we still have the scaler times two so this is four degrees So this first one is negative four degrees this one is four degrees this one is going to be It's going to be taking the scaler and doing a little bit more math So it kind of pushes it a little bit further out a little bit further out and etc Right, so these ones did times two. Oh, these ones actually don't go as far. See they're not times two So they're just going to go out exactly as the scaler is so four degrees And these ones we're going to be well, I guess they're two degrees and those ones were four Anyway, you can kind of see what's going on and how they're being fanned out as I'm just using a selector here That's looking to see the specific one and I'm fanning them out either negative or positive times two or not times two So kind of a little tricky, I guess because it's math, but once the math was done. It was pretty smooth sailing after that Okay, and the next part that we have so we've talked about transform origin. We've talked about the Kind of rotation that's being calculated on these. Let's go look at the actual Transform style that's being applied here and see Why I did this also so we'll check this out. So here's transform We've got rotate set to the variable r or zero degrees So if there is no rotation, we've got like a fallback value at zero degrees Same thing with translate y being set to t which is short for translate and or x or of zero pixel So if I hover let's set hover on here hover We can see that t is being set to 50 and that's why it's being offset on its translate y by 50 And what's kind of cool, too So if we take off the hover we saw earlier that when these are fanned out really heavily I'll go to center that these things are fanning out and they're being transformed on that translate y in their own angle Based on this sort of rotation that's already happened, right? It rotated and then went and translated Let's again go look at our transform We rotate and then translate we will get a different result if we translate and then rotate It would then move it up and then rotate it to match the angle Which is not going to give us the hover effect that we expect here as they're angled So let's go try that out because I've got some example code here that does that. Oh, and then this last part here We're transitioning transform origin over half a second using a squishy ease and that's why they sort of bounce see little bouncy bounce That's a little open props easing value. You can go take it adds a little kind of squish to things So it does like a little bit of a bounce in and then it doesn't bounce out So it has bounces on both sides, which is fun and then we do the transform. It's like when I hover That's just using an ease in out. So nothing kind of bouncy in that gesture, but okay, so let's turn off our transition Let's go back to this transition, which is going to transition the transform origin Translate and rotate so we're actually going to go change the way that we're doing these and we're going to rotate instead So here we'll take this value R. I think we can just do like rotate var R here. Yes, we might have to do that for each of these Yep, so I'll take this one. I'll just pop this to each of these. So now we're using individual transforms This is just fun to do right now. Anyway, look at that. Just watch them. I'll pop into their space Okay, so now they're using individual transforms to rotate and we're going to use individual transforms to Do the hover effect, right? So we translate and it goes on X by 50 So now I could I should be able to have all the same working demos Yep, all the demos work great. We can see them move amongst all those different positions But when I hover look, they just go up They're like literally moving up and that's not the effect we want. What's going on here is essentially using the Shorthands like that these new individual transforms of rotate, you know some value and translate Two values by using those you aren't in control of the order It's going to translate first and then rotate That's part of the value of these is they allow you to sort of more succinctly access these transform points But you aren't in control of the order anymore and that might not matter in a lot of cases But look it totally mattered for what I was building I needed these to hover and kind of shoot out from where they were already rotated and so that meant I needed to not use Individual transforms instead. I needed to manage these by hand. We'll go through all these again. That's cool Here we go and do and do I think I missed one Nope, I got that one and then we also need to change the hover so that the hover no longer uses the Translate property, but sets our custom property. Okay, so now we've got our custom properties all set again We need to update the Transform back to the one that uses our custom properties take off the transition that was using the Individual transform properties and go back to the one that's transforming transform origin and transform itself now as we hover Well, let's take off this hover Now as we hover you can see them protruding from their actual rotation. It's really easy to hear It's the or see here in the centered one as they sort of look at that one It kind of almost looks like it arcs out, but it's totally just sliding this way Whereas this one's gonna slide this way so we can tell that the rotation happened first and then the translate So kind of a cool little niche moment where individual transforms. I wanted to use them. They're super new They're really fun But they were ineffective because I needed to manage the order here So again, I wanted to rotate first then translate here. Let's just do this Let's take this rotation since now I'm managing transform and do it afterwards and hover look they just move up It's totally lame Let's go back to the better model Drop that come over here. Yes hit enter ah It's restored. Okay, so cool So the last thing we have to cover is the use of has so when I select one of these over here They're essentially setting the checked attribute on this particular bottom center one And so here I'll look at this element here. I'll look at the selector It says HTML has mode bottom center checked Then go find the card stack and find each card and set their transition origin to bottom here If we set bottom left we select another one. We can see the DevTools is updated to bottom left I go to the center one down here You can see that we've updated to mode better bottom center checked card stack card So HTML is the subject looking for any descendant named mode better bottom center and to see if it's checked So it's kind of cool. We're anchoring our state off of the HTML Looking for any descendant and then from HTML We're going to go look for card stacks and cards given that this is true So if this is checked, it's going to find all the cards and set this particular value and we get what we need here Let's go back to center so that I can drop the gap here and not have something so wild Excellent there you go much tamer, but still looks great And so that's what's going on with the has usage So has is just looking to see if one of these is checked and then it's pivoting the whole application state off of that and Targeting and setting styles for anything that it wants anywhere on the page. Yes It is that powerful any nested element anywhere on the DOM can be discovered on the HTML And then past new values down to anyone else in the DOM. It is so cool. So that is it for today's GUI challenge I hope you liked this. I thought this was a really fun demo. We're just making a card stack So it's not a component today, but it did build upon some really fun Like ideas here, which is I don't think people often animate transform origin And it ends up being a really fun way to manage this stack of cards I think if you're managing a stack, you should use grid It makes it really nice for just assigning everything that same cell we get to work within, you know Sized items. We're not just positioning absolute something and sort of losing sizing information We're staying in flow like we could put more content underneath here And it knows what to do because these items are still filling up that cell that they were given this whole layout Isn't devoid of the sizing information. It's size full. It's rich of information We saw that has is coming in Firefox soon and we got to Build something. I don't know very visually interesting. Plus, you know, it worked in light mode, too We saw it was looked good in Safari in light demo Let's check out the light theme in here just because it can kind of be nice to see a Complementary set of of styles here and look at the cards nice and bright and vibrant. I hope you enjoyed this GUI challenge I sure had a bunch of fun making it and I really want to see how you would do this How would you stack your cards together? What sort of animations are you doing to your stack of cards? And let's build stuff together and grow together. I'll see y'all in the next GUI challenge. Take it easy y'all. Bye