Advanced Dropdown Menu - React & CSS Animation Tutorial for Beginners

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I don't log into Facebook often but the last time I did I was super impressed by its simple intuitive and fast new UI in today's video I'll show you how to reverse engineer some of its UI features specifically the top navigation bar is icon buttons and this multi-level animated drop-down will do it using HTML CSS and because I mentioned the word Facebook I'm legally obligated to use react in this demo in the following code tutorial you'll learn how to create icon buttons with flexbox you'll learn how to use CSS transforms to create sliding animations and fundamental concepts in react white component composition hooks and how to create CSS animations based on the state of your react application and I'll throw in a bunch of other cool tips along the way if you're new here like and subscribe and let me know if you want to see more beginner friendly UI tutorials like this in the comments before we get started let's take a closer look at what we're building today by the end of this video you'll have several reusable react components that you can use for navigation and drop downs at the top we have a navbar component where the children are nav items represented at icon buttons these buttons have children that you can toggle on or off by clicking them when we click the carrot it renders our drop down component it contains multiple drop down items and the ones with a chevron can toggle to a secondary drop down menu notice how the hold menu slides out to the left and the new one comes in from the right and because the height of the two menus won't be the same we'll animate that as well now before we get started I'd just like to say this is a beginner friendly video but we move at a very fast pace on this channel so feel free to pause the video or slow down the playback speed as you follow along the first thing we'll need is a react app assuming you have no js' installed open up the command line and run npx create react app and of course the name of our app is Facebook to keep this demo simple I'm going to delete everything that's not the index JSF KS or index dot CSS files the index.js file is your initial entry point I'll go ahead and remove the serviceworker stuff here then you can ignore this file for the rest of the video from there I'm removing all the boilerplate code from the app.js file will be using functional react components in this video when you see a function whose name starts with a capital letter you can think of that as a component the return value of a functional component is your UI or HTML or more specifically JSX JSX is not actually HTML but it's a syntax extension for JavaScript that allows you to write HTML like templates in your components but before we get too deep into react let's open up the index CSS file the CSS in this video is pretty generic so feel free to use it with your favorite framework I'm starting by defining some global CSS variables that we can think of as our theme and I'm also defining a speed variable that represents the animation speed which will come into play later in the video then below that I'm overriding the default unordered list style and then for our link elements I'll match them to the text color variable in our color scheme that takes care of our initial setup now we're ready to start building the top navigation bar react and especially functional components make it really easy to break your application down into a lot of small reusable pieces and this is a practice that we call a component composition in our App J's file we'll define a new component named navbar and it returns JSX inside these parentheses we'll go ahead and add an HTML nav element with an unordered list inside of it we can apply a CSS class to these elements using class name notice how this is different than regular HTML which is normally just class and we'll apply a class for navbar and navbar now have to make these elements easy to style now if we go up to the JSX for the app component we can declare this navbar there and notice how we declare it almost like a regular HTML element now I'm going to open up the CSS here on the right side and we'll apply some styles to the navbar the navbar is basically just a rectangle that sits at the top we'll give it a fixed height based on our nav size variable and then some coloring and padding the unordered list that sits inside the nav is the container for the children which we'll set up as a flexible row we want it to take up 100% of the width and the height of the parent and then we'll set the display property to flex and we could have all the children's start on the right-hand side instead of the default left side by saying justified content flex and now at this point we have some actual UI that we can take a look at go ahead and run NPM start from the command line to serve your app it should open in the browser automatically and you should see this horizontal gray bar up at the top and now the question becomes how do we add items or children inside the navbar in react components can pass data and UI elements to each other using props add props as an argument to your function and then you can reference it in your template props has a built in property name children and it will project or reference any UI elements that you pass in inside of the actual of that component for example if we go up to our navbar and add a list item inside of its tags it will be rendered in the location that we called prop stock children so if we open up the browser you should see the letter X here up in the top left corner but this gives us a great opportunity to create a new component called a nav item our nav item component will also take props and we'll set up a list item as its main element and then we'll nest in a or link element inside of it the a element represents the icon button so we'll give it a CSS class accordingly now this time instead of referencing props children we're going to pass our own custom prop called an icon instead of adding UI elements inside of the tags we reference our icon prop as we would with a regular HTML attribute so props allow you to pass data from the parent to the child similar to how you might pass an argument to a JavaScript function because remember your react component is just a JavaScript function for now I'm just going to pass some emoji icons so we can focus on the CSS each nav item is a box that is slightly smaller than the nav bar itself an easy way to manage its width is to calculate it dynamically so we'll take our nav size variable which is 60 pixels and we'll multiply it by 0.08 or 80% with the calc function now each of these now items should display their children directly in the center we can easily do that with flexbox by aligning items to the center and just find the content to the center so that gives us a box with its children in the middle but now we want an icon button with a circular shape I'm going to scope a new CSS variable to this class called button size it also uses the calc function to give us a size that is exactly 50% of the original navbar size and now we can apply that value to the width and the height of this class and then to make the shape circular we can apply a border radius of 50% which creates a perfect circle now inside of this circle we also want to Center the children directly in the middle so again we'll set up a Flex container and a line and justify everything to the center if you open your app in the browser you should now see these three icon buttons here at the top as an added touch we might want to change the color slightly when these items are hovered over an easy way to handle that is with a CSS transition we'll apply it to the filter property and set it to a duration of 300 milliseconds then we'll target the hover cito selector on the icon button and we'll filter its brightness to 1.2 to make it slightly brighter as we have over it however in the full demo and on Facebook you'll notice that it's using SVG icons you can find all the SVG s I used in the source code on github they live in this icons directory but how do we use these SVG icons and react it's actually very easy to use an SVG icon as a react component directly in your code at an import statement to the top of the file that references the path to your SVG icon you import a react component and then name it whatever you want using the as keyword and then you can do the same thing for all the other SVG is that you want to use in your code from there we can go back down to our navbar and instead of using an emoji we'll use braces to pass on one of our SVG components directly and now your icon buttons can handle both SVG graphics and emoji strings equally but your SVG's don't inherit a size by default so we'll want to go ahead and set a fixed width and height for them and now if we preview things in the browser we should have an icon nap that is very similar to the actual facebook UI and now we're ready for the fun part building an animated multi-level drop-down menu now the reason we're not passing the icon as a direct child of an ad item is because some of our nav items might have a drop-down menu and we want that to serve as the children we'll add a fourth nav item here with a carrot icon and our drop-down will go inside of it now in order to open and close a drop down our nav item will need to have some state or in other words some data that changes throughout the lifecycle of the app we can manage state and react using a hook called use state in our nav item components we call the use state function and it returns us with two values the values are returned in an array so we can D structure them as variables here using bracket the first value is the state which in our case is called open and is a boolean value that tells us whether or not the drop-down menu is open the second value is a function that you can use to change the state we can also set a default value as the argument to use state and of course we want the drop-down to be closed by default that sets up the initial state but now we want the user to be able to change the state when they click on the nav item button we can do that by going down to our link element and we'll add an on click event handler when the user clicks a button it will use the set open function that we got from new state and it will flip the open value to the opposite of whatever it currently is putting a bang in front of a boolean gives you its opposite value and that can be useful for toggling things on and off okay so now that user has a way to toggle State but now we need to do something useful with the state in our case we want to show the drop down when the open state is set to true below the link will add braces and if the open property is true then we'll show the prop stock children if the open state is false then nothing will be shown here we can test things out by going to our nab item component adding a hello world and you should see that appear when you click on the button obviously it looks terrible so let's make a drop down component to fix that we'll add another function for drop down menu and we'll have it return a div with a class of drop-down then we'll add our drop down menu as the child of the nav item now similar to our nav bar a drop down has multiple drop down items but in this example I'm going to nest that component directly in the drop down menu the drop down item will simply be a link with a class name of menu item and then we'll pass and props children to control the text of that link now you may have noticed in the demo that some of these links have an icon on the left and some have an icon on the right we can handle that logic in a flexible way by adding slots for a left icon and a right icon when you pass in a left icon or right icon prop it'll be rendered but if you leave it blank then it just won't render anything at all we can see it and use down here in the drop down a basic drop down item we'll just take some text as a child but if you want to show an icon on the left or right you can also pass in the icon prop and pass it a component or emoji string now in order to get things looking right let's go back to our CSS the drop down menu on Facebook overlaps just slightly with the top navbar and we can achieve that effect by using absolute positioning it allows us to explicitly offset an element based on its container from the top of the parent nav bar will move the drop down down 558 pixels that means it'll overlap by 2 pixels with the top nav bar which has a height of 60 we can give it a fixed width of 300 pixels and then we'll move it over to the left by translating it over the x-axis by 45% we'll give it some colors and padding and we'll want to make sure the overflow property is set to hidden what this will do is hide any child elements if they overlap this container that's important because in a minute here we'll be sliding in multiple menus through this container now the drop down has multiple menu items we'll set these up as Flex containers that align their items to the center in the context of a row that means vertical alignment now when a user hovers over a menu item we want to animate the background color so we'll go ahead and set up a transition for the background then we can target the menu items hover pseudo selector and change the background color to something a little bit lighter as a final touch we want the right icon in the row to be pushed all the way to the right side with flexbox you can set the left margin of the last item to auto and that will push it all the way to the right and everything else to the left and now our drop down menu is starting to take shape at this point we have a fully functional single level drop down but we require an animated multi level drop down to help us along the way we'll install a very popular package called react transition group it will help us control the conditional logic for rendering multiple menus and transitioning between them when they're added or removed from the application once installed go ahead and import the CSS transition component from the package then we need to give our drop-down menu some state to specify which menu is currently visible we'll set the main menu as the default and then we'll also show a settings and animals menu as well now our active menu is the state or the name of the menu and set active menu is how we change it now that we have state we can animate elements in or out using CSS transition we can go ahead and wrap our current drop-down elements in the CSS transition component it's looking for a prop of in which when truthy will render and animate its children into the UI in other words when the active menu equals main then we want to show the children inside of this component I'm also adding a second property called unmount on exit which completely removes these children when they're not active next we'll set a timeout which defines the duration of the animation and the last prop we need to add here is class names which we'll set to menu primary for this primary main menu now here's how the CSS transition actually works it looks for the first child element which we'll set up here as it did then when it's in prop changes it will add or remove CSS classes to this element based on the state of the animation and it uses the class names prop to prefix those classes CSS transition doesn't actually animate anything directly instead it adds and removes classes based on the state of the animation so you can handle the animations in your CSS notice how I'm setting up four different classes here menu primary enter interactive exit and exit active when the in prop first becomes true it will add the menu primary enter class to the div after a timeout of 500ml it then adds the menu primary interactive class now when the in prop becomes false it does the exact opposite it adds the exit class than the exit active class this means you can easily create an animation using CSS transitions we want our main menu to slide in from left to right so initially we'll translate it to the left by a hundred and ten percent so it'll be completely invisible off to the left after five hundred milliseconds we'll bring the translate back to zero so it'll be in its normal position then we can animate it using the transition property using our speed variable and a timing function of ease as you can see here CSS is doing the animation while react is toggling the classes for you now to animate out will do basically the same thing just in the opposite direction we'll translate from zero to a negative one hundred and ten percent now at this point everything should be exactly the same that's because we need a secondary menu to toggle to let's get started with that second menu by copying our CSS transition and pasting it directly under the existing one instead of checking the active menu for main we'll check the active menu for settings for class names we'll use menu secondary because we want to set up different classes for this menu to slide from right to left now the class is worth in exactly the same way the only difference is that we're translating to positive 110 percent versus negative 110 percent the effect is that the secondary menu will be offset to the right and then it will slide in to the left and that's all it takes to build the basic slide in slide-out animation but we are missing one piece of the puzzle and that's a way for the user to activate or deactivate a menu we have our set active menu function from you stayed so we'll go ahead and bind that to the click event on the drop-down item button but instead of hard-coding a value here we're going to look for a prop that's passed down from the parent component and we'll want to make sure that prop exists before we call the set active menu function now to get our demo working we can go down to any drop-down item and set the go to menu prop to whatever menu we want to navigate to which in our case will either be settings or main and now if you open up your demo you should have a functional multi level drop-down but we're not done quite yet there's still some additional polish that we have to take care of go back to your demo and add a bunch of drop-down items to one of the menus notice how the height is not animated it just snaps into place and totally ruins the entire animation this happens because the old menu hasn't been completely removed from the by the time the new menu is visible what we need is a more dynamic way to manage the height let's create some state for the height of the menu then we'll create a function called calculate height and this function takes a Dom element as its argument that's because a Dom element has a property called offset height which contains the actual height and pixels of that element and now you might be wondering where do we get this element and when do we call this function well the CSS transition has lifecycle hooks that we can tap into one of these hooks is on Enter it calls a callback as soon as the enter class is first added to the element and it also provides the element as an argument which means we can simply pass in our calc I function here as the prop value that will recalculate the height of the menu now we just need to apply it as a style to the drop down itself we can go up to the style attribute and dynamically pass in the height from our state and that leaves us with one final step to animate it go to the drop down class in your CSS and add a transition for the height now when you go back to the demo your drop down should magically shrink and grow based on the size of the current menu and with that I'm gonna go ahead and wrap things up there if this video helped you please like and subscribe and let me know what you want to see next in the comments thanks for watching and I will see you in the next one [Music] you
Info
Channel: Fireship
Views: 483,930
Rating: undefined out of 5
Keywords: webdev, app development, lesson, tutorial, react, reactjs, js, javascript, html, css, html tutorial, css tutorial, react beginners, web dev tutorial, dropdown menu, react animation, css animation
Id: IF6k0uZuypA
Channel Id: undefined
Length: 16min 52sec (1012 seconds)
Published: Fri Apr 17 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.