Rebuild an Awwwards Portfolio Landing Page with Nextjs, Framer Motion and GSAP

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
lately I've been receiving a lot of requests to recreate a bunch of different parts of Dennis nielenberg's portfolio honestly I tried to think of how I could split everything in different videos but I said it I'll just remake the whole page and also big shout out to Dennis for this website all credits to him he's an amazing developer so the portfolio has a bunch of different moving Parts I decided to split them into seven main components with two extra components that will be shared among the others the main Tech stack for this landing page will be next just as the react framework SAS for The Styling locomotive scroll for the smooth scroll and The Parallax and firmer motion and g-sub for all of the animations and if you're interested you can find the source code and the live demo in the description below now in my past videos I already took a look at the landing page and the project component and so I've integrated them in the project right now so we can save some time and I've also initialized a locomotive scroll just to have a smooth scroll and so we have something like this for a starter project now the first components will be the header so here I start from the structure that I created in my previous video for the curved menu and I add some h HTML and CSS using the translate x value the padding right and all of that with an overflow hidden and with that we have this nice logo animation and the next step is to work on the knob here we have like an indicator so this can be made very quickly using HTML and CSS we can see that we have a nice little indicator now I've also put the burger menu in scale zero if I put it back to scale one you're going to see that we have like two menu overlapping on top of each others so what I want to do is initialize it at scale 0 and then I'm going to use gsop to animate it and make it appear after a certain amount of scroll alright here I initialize a use layout effect hook and I initialize the scroll trigger plugin for gstop and then I create a ref for the burger and with that we're ready to add a scroll trigger animation on the burger menu so what I'm going to do here is do a g sub.2 and I will Target the burger dot current because it's a ref and I will create here a scroll trigger and the trigger will be the document the start will be zero the end will be a full height of the window and then I can add a on leave and a on enter back and it's here that I will animate the scale of the burger so what I can do is a g sub 2 and I can do the burger dot current and I can go ahead and change the scale when we leave we change the scale back to one and then when we enter back it's the reverse we're gonna do zero and then I can add a little transition and if I save that I can see here that the burger menu is initialized at scale zero and then when I scroll for a hundred viewport height the burger menu appears and I can click on it and Trigger the menu and if I scroll back up the scale is resetted back to zero and with that we have a really nice header and the next component will be the description here I create the description components and I import it inside of the page.js then I create some simple HTML and CSS I have a phrase that I split into individual words so that I can then animate them and then I add some CSS to make everything look good and with that I have a nice simple layout here and the good thing is our paragraph here is separated into words so I can then animate this using firmware motion so for the animation I create anonym.js file where I create an opacity and a slide up animation and I add a motion on the spawn and on the second paragraph and then I use the use in view Hook from frame motion to check when the container comes inside of the view and I can control the animation with that and as a result if we scroll in we can see that the description gets animated we have an opacity on this paragraph and here we have a word by word animation but the problem here is there is no delay between the words they all appear at the same time and we can easily fix that by passing here a custom value and we can give the index and then we can go here inside of the animation and the slide up animation here will have the index here and we can have a delay here and we can do like 0.01 multiplied by the index and if we save that we now have a word by word animation with a slight delay we could have like one even more just to show you guys and here we have a word by word animation but obviously that's a bit too much I'm just going to fix it so maybe 0.02 and now we have a nice word by word animation and then we're ready to work on the button here it's the last element there is a slight Parallax so we can do that with locomotive scope so here I'm adding some basic HTML and CSS to make a simple button and with that we have a nice button here it's placed in position absolute so it's like in a nice place and then if we want to add a parallax on top of that we can simply go in the parents container here of the button and we can do data scroll meaning we want this element to be observed by the locomotive library and then we can do data scroll speed to create a parallax and then we can do like 0.1 and with that we can see that there is a nice Parallax right the button is not moving at the same speed than the rest of the elements and now we'll increase the level of difficulty with the sliding images component framework motion is used here to track the progress of the scroll and we can use that progress to animate the sliders and the overlapping Circle so for the sliders I import two arrays containing objects with a certain color and a certain source and then I use HTML to create a slider container and I map those arrays to return a project with a next image inside of them and then I'll add some styling to make everything look good I make sure the slider has a width that's a bit bigger than the size of the window and without I have a nice slider here and I want to be able to translate on the x-axis the sliders on scroll now I'm going to start by importing two hooks from firmer motion one of them is the use scroll and the other one is the use transform and then I've created a ref for the container and I've added it to the div and now what I want to do is track the progress of the scroll and what we can do here is extract the scroll y progress from the use scroll hook of framework motion and we can specify here because if we don't specify anything we're going to have the scroll wide progress of the entire document and that's not what we want we want only the progress of the container that we've created here and so what we can do is specify a container to be the container that we just created and then we can specify the offset that we want because we see here that the scroll progress returns a value between 0 and 1. and so we need to specify like an offset to basically tell firmer motion what do we want to be zero and what do we want to be one right and in our case we want the zero to be this starting point here basically when the bottom of the window hits the top of the container and so what we can do here is specify the offset to be we set the start of the container and the end of the window and then the end would be at the end here which would be the top of the window and the bottom of the container and so what we will do is end of the container and the start of the window and with that we have a value between 0 0 and 1 depending on the Scroll starting from this point here until this point here and with that we can create two x values so one for the first slider and one for the second slider right so we can start with the first one and we're going to use the use transform hook and we're gonna give us a value to transform the scroll y progress and then we can specify 0 and 1. those are the values of the scroll y progress and we want to transform those values to be 0 and 150 and so that means that we can translate on the x-axis from 0 to 150 depending on the progress of the scroll and then we can create another value and this one we're going to do it on the other side and then I've added a motion on the two slider and I can specify a style and I can say the X should be the X1 that I defined here for the first slider and the second slider the X should be the X2 and then here I need to change it's not the container it's the Target and if I save that I can see that I have now my slider moving left and right which is exactly what we you want and now I'm going to work on this overlay Circle here so for the circle I add two divs and then I go into styling and I create a buck Shadow and I give a crazy high height and a big width of 120 with a left 10 so that it's a bit bigger than the window and then I give a border radius at the bottom to have a circular div you can see that we have a massive div here with a circle if I animate the height of the container I can do like 25 I can see that it's reducing the height if I do 10 it's almost a null curve and that's because the circle here has a height that depends on the parent and so I'm going to leave the height at 0 at first and then I'm gonna go in the JavaScript and I'm going to create another Transformer I'm gonna do one for the height I'll animate initially a height of 50. that will go to zero when these scroll progress reaches one and I can take that high adding motion and give the height to the circle container and if I save that we can see that we have a nice circle now I cannot scroll more than that I'm just going to add some margin bottom to show you guys here and here we can see that we have a circle and when we scroll it gets flattened and more and more and we have like a nice shadow and so of course now it looks weird but with the footer it's gonna look great if we look at the demo we can see that the footer will be underneath and it's going to make a lot more sense than it does now it looks a bit weird but it's gonna make sense after that we can now work on the contact component which is like the footer all right so here's the footer I went ahead and skipped the HTML and the CSS part because it's a lot of small details that are not really relevant to the animations and as you can see when I scroll we still have like this curve here from the circle of these sliding images and so what we can do is go back in these sliding images here and instead of putting the height at zero when the scroll progress is one we can reduce that when the scroll progress is equal to 0.8 then we want to have a zero of height and with that we're going to make sure we have a straight line maybe you can do like 0.9 and with that we have a nice straight line when we reach the bottom of the footer now if you look at the demo here we can see that there are three animations on the footer there's one on the Arrow one on the button and one on the container itself so we can start with those two smaller elements and we're going to use the same concept as these sliding images we're going to use the use transform and the use scroll from firmware motion and so here I've added a container to the main container and initialized a scrollwide progress using the container as the Target and then I need to specify an offset and that's always the tricky part when it comes to using the use Curl hook so we can take a look here at the footer and we basically want to start tracking when the window is at the bottom and it's the top of the container so we can do at the start of the container and at the end of the window and then the end should be here the end of the container and the end of the window as well so we can do end and now we effectively have a nice scroll wide progress that we can use inside of a use transform so here I have an x value and a rotate value that uses that progress for the X it goes from 0 to 100 pixels and the rotation goes from 120 degrees to 90 degrees and I can now use those values to add them to the button and the arrow so for the button here I've added a motion and a start with the X and for the arrow I've added the motion as well and specific by the position and I put the scale 2 just to have it a bit bigger and if I try this here we can see that the arrow is rotating and we can see that the button is translating on the line which is a really nice effect and the last thing we want to add is a parallax on the footer if we look at the demo here we can see that the footer here is almost fixed so it is still scrolling but almost not at all and we can create that by basically creating a force that will go in the opposite direction of the scroll and so what that means is we want to create a y value that's going to go in the negative and that way it's going to go against the scroll and it will give the illusion that the footer is not really scrolling so we can create that pretty easily using the same thing we're going to use the use transform hook and then we're going to use the scroll y progress from zero to one and then we're going to initialize the Y at -500 to 0 and then if I put that y to the main container I can see that my photo here has initially a y of minus 500 and that's why it's like overlapping on top of the sliding images component and then if I scroll down kind of goes back into place and so that's exactly what we want it might looks messy but all we need to do is just adjust the z-index and put a background white on these sliding images so I'm going to go here in these sliding images and I can do a z index too and a background color white and now it's overlapping on top of the footer and we have this nice Parallax effect on the footer very easily and with all of that we have a very nice landing page we have all of our components integrated in the page we have a nice footer sliding images a nice project Gallery a description and the landing page and we have this nice menu here that transforms into a burger menu so now that all the main components are integrated we can create an introduction to the website so the first thing we want to do here for the introduction is create a state that will track if our animation is loaded or not so we can have here a const is loading set is loading here so now that we have a state we can do conditional rendering if the app is loading then we want to return the preloader and then we can go ahead and create the preloader as a component here and in this landing page we don't have any data fetching so all we need to do is set that initially yes the app is loading and then we can manually add a timeout to set the loading to false after two seconds and if we refresh the page we can see that we are loading and after two seconds it disappears and then we can also go in the global CSS here and specify that the cursor should be initially a weight cursor and then in the JavaScript we're going to reset that cursor to default so if I refresh the page we have a weight cursor and after two seconds the loading disappears and our cursor becomes the default again and now I'm just adding a class name and some styling to make the loader take the full width and the full height of the window and with that I have a nice loader that's on top of everything else but now it looks a bit weird right it's just it appears and it disappears and since we are mounting and unmounting the components what we can add is the animate presence Hook from firmer motion and we can put it in mode weight and that will basically Force the preloader to have its exit animation before unmounting so here I'm creating a non-name.js file where I declare an animation that will slide the division up and then I go in the HTML and I add the motion in front of the div I specify the variance and initial and an exit value and if I save this and I refresh we can see that we have the loading and then the animation will unmount and we have this nice effect and then for the text animation I add an array of words and I use the used effect hook to be triggered every time I set the index and I add a timeout with a certain delay depending on which index we are at and then I add a paragraph with the word of the current index and I go in the anim.js and I add a slight opacity animation and if I save that we can see that we have this nice next animation and honestly it's a decent loading animation but we can add an extra touch of it by adding a curve and we're basically going to make that curve the same way that we're making the curve for the menu here we're going to use an SVG and animate it using firmer motion so here I create a state that will encapsulate the dimension of the window and then I can add a conditional rendering and only return the paragraph and the SVG if the height exists and then I Define my initial path by drawing a custom SVG using the quadratic busy curve to create a curve and then I'll add some styling just to make everything look good and if we save that we can see that we have our text here and then we have a curve and now all we need to do is animate that curve using firmer motion so I'm going to create here a Target path and I'm going to reset the curve back to a null point and then I can create the curve animation here and I can add a transition the same as for the slide up animation here and then I just add the motion to the path with the Curve as a variant and if I save that we should have our introduction component working here but there's one bug that could occur and that's if I go on the website side and then in the loading I decide to scroll I go up here I end up in the place where I scrolled so what we can do to avoid that is in the page.js here we also want to do a window dot scroll to and then we're going to scroll to zero zero and that will avoid to have like this weird bug if the user decides to scroll so we're not ready to add some polishing to this landing page so we can start the publishing process by creating a reusable component for the buttons so this is essentially what we're trying to do we're going to have a button here that can take any size for example this size here or this size here and this size here right and what we want to do is have a circle that's going to be at the bottom here at first and then when we hover that circle is going to slide up and then when we hover out that circle is going to slide away on top all right so here I'm creating a button component it's going to be a div with some styling and it's going to return the children and the circle and as a parameter it's going to take a background color and any amount of attributes that we want and then I go inside of the description and I replace the button as an example and so here I've added some styling to to the circle we have a height of 150 percent and a width of a hundred percent and so here it is and now we need to find a way to make it slide up the button when we hover so I've added two mouse events to the main division here and we're basically going to use G sub to animate all of that so we need to create a reference to the circle so we can have here a circle and create a reference so for now let's try to move that Circle up a bit so we can do on Mouse enter we can create a j sub 2 and then we can Target here the circle and then we can try moving the Top Value here let's try to do like minus 25 with a duration of like 0.4 second and then if I try this I'm going to hover and see the circle is perfectly centered with the button because it has a height of 150 percent and so minus 25 will Center it perfectly on the y-axis and inside of that Mouse Leaf I'm going to slide the circle even higher so I can do minus 150 if I hover the circle is moving inside and if I hover out the circle is now moving away and that way we can create this kind of curve animation so I'm going to add here an overflow hidden to the main container of the button and if I try this with an overflow hidden it kind of gives the illusion of creating a curve and I can create this illusion even more by boosting the width to maybe 150 on Mouse enter and the width to maybe 125 on Mouse sleeve and now if I try this it looks really clean but we have a problem the animation only works once and we have to refresh the page what we could do to fix that problem really quickly is add another gstop to and put it back to where it was in the beginning we now have the animation working fine and if I hover very fast it works fine but we're gonna have a problem when we start changing the duration so I'm going to put the duration that I want now it kind of gets buggy it works if I don't do anything weird but if I start moving my mouse really fast like this it kind of gets buggy and it's quite a problem if I use this technique what we can do is use the timeline of gsop and instead of putting the two directly here I'm just going to Target the timeline and do a tween from Two and so the from value will be a label I want to do the enter to the exit meaning it's going to start at the enter and it's going to go to the exit it's not going to play the exit animation though and then when we leave the mouse what we want to do is just do a play and if I try this this works really well and if I move my mouth in a weird way we can see that we don't have the problem that we had before and then we can add a little extra step to make this even cleaner if we look at the demo here we can see that the button if I leave my mouse and then I I quit it stays the circle stays a bit longer right it kind of stays and then if I move my my mouse fast it leaves right away so this this is a really nice little detail that we can add so what we can do to create this effect is create a timeout of like 0.2 seconds but let's do 0.3 seconds but this can create a bug and I can show it like this see how it goes away without my mouse leaving I'm gonna go fast and it just it just goes away that's that's a bug and so what we can do to fix that final problem is create here a timeline not a timeline a timeout ID and we're gonna have it at null at first and then when we create a timeout we're gonna basically set that timeout ID value to be this timeout and then we can check that if there is a timeout ID then we want to clear the timeout with that timeout ID and then I'm going to do the timeout ID is equal to no so with that we have a really nice button if we hover and we leave it stays for a bit if we go fast it goes away and there is no bug with the button and finally we can create a magnetic effect to most clickable Elements by creating a wrapper that will clone the children that can then be animated with g-sub so here I have the basic magnetic component I simply want to return the element so what I could do is do children like this and so that way it's going to return everything that is wrapped under this magnetic component but I also want to add a magnetic reference to it so that I can then add like effects with mouse events listener and all of that what I can do here instead of returning the Raw our children what I can do is do react and do a clone element and I need to remove the brackets here and then I'm going to basically clone the children and I'm going to add a reference being the magnetic element and then for example I can go inside of the button it's really convenient what I can do is import the magnetic here and I can simply wrap the button inside of the magnetic component and that way everything we do in the magnetic components will also be applied to the button and then here I have the mouse event listeners that I added on the magnetic reference and then to start moving the element what I will use is the quick to function from gsop so I'm going to create a next two and the white and this technique here is the same that I used to create this project gallery to create like this moving model so if you're interested you can check out this tutorial alright so here I have the X2 and the Y2 function which are quick two functions by g-sub this is the magnetic effect that we're trying to create if I move my mouse out I basically want to reset the X and the Y to zero so what I can do is on my sleeve X to 0 and Y to zero that's pretty logical right when we leave the mouse we reset back everything to zero and it has like this wobbly effect because we are using the elastic easing and then to tell the element to move at a certain position what we can do is extract the client X and the client y from the event and then we could try to do X2 and Target the client X and the client y okay so it's definitely really buggy I can see that the mouse Leaf functions fine but I feel like it's not getting the right position so to have like the accurate position that we want we need to subtract the position of the current element and so for that we can extract the width the height the left and the top value of the magnetic element by getting first of all the magnetic element and then getting the bounding client rect what we need to do is for example on the X we're gonna have the client X and we need to subtract the left position but also add the width divided by two and for the height it's going to be the same thing and we are adding here the width divided by 2 and the height divided by 2 because the top and left position are like the top left corner and so we need to add half of the width and half of the height to have like the center value and with that we should have something that makes much more sense and we now have a nice magnetic button but it's kind of moving a lot so what we can do is simply reduce that value by maybe 0.5 and then we're going to put back the reset to zero and with that we have a super nice magnetic effect and so what I do here is I go across all of the application and I add the magnetic to the elements that I want and I also add the button to the button that I want and so now I've added the magnetic and the button across the website and we can see that I have here a magnetic on the header I have the magnetic on the button on the button here as well and on the footer here and also have it on the header and that's the power of reusable components and I think that with that we are officially done with the landing page it was a lot of work it was a long tutorial let me know in the comment section if you prefer like smaller tutorials or if you like big ones like this one I'm still unsure which format is the best so please give me your feedback and also if you like the video If you learned something leave a like subscribe and I'll see in the next one bye
Info
Channel: Olivier Larose
Views: 19,557
Rating: undefined out of 5
Keywords:
Id: Powk6f1qe3k
Channel Id: undefined
Length: 23min 22sec (1402 seconds)
Published: Wed Jul 26 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.