0:00
In this video, I'm going to show you how to create this animated CSS hamburger menu
0:04
It's written in only CSS with no JavaScript at all, and it's using CSS variables for pretty much everything
0:10
So if you want to change something like the height or length of the bars, you can do that in one place
0:14
and all of the rest of the code will automatically update to take that into account
0:21
Welcome back to WebDef Simplified. My name's Kyle, and my job is to simplify the web for you, so you can start building your dream project sooner
0:27
And as you can see, we have our hamburger menu on the right hand side of the screen, and we have this really smooth animation
0:32
And again, everything is just CSS only. And it's also completely responsive for accessibility, which is really great
0:38
So you can use the space bar and tab, and it's going to work just fine. Now, like I said, this is all using CSS variables
0:44
So if I went into my code and I changed the bar height to be really big, like 20 pixels, for example
0:48
you can see when I click, the X is still formed perfectly to the exact size to make a perfect X
0:53
I can also come in here and I can change, for example, the gap instead. Let's make that really large
0:58
And now when I click, you can see again, still the X is perfectly formed. So I can change one variable in my CSS code and all of the rest of the code just falls into place perfectly
1:06
This is something that almost no other hamburger menu you see is going to do because they're all super hard-coded and really finicky
1:12
But this code is automatically going to make adjustments based on the variables you define
1:16
Now let's bring this code back to what we had before and I can actually show you how to start building this
1:20
So the first thing we need is we need to have an index HTML file and we're going to need some CSS
1:25
So let's do that in a styles.cass. So I can come in here, get all my boilerplate code using Emmett
1:30
And if you want to learn how I did that, I have a full tutorial on it. I'll link in the cards and description for you on Emmett
1:35
And then we can come in here and we can create a link tag. We're going to do CSS just like that
1:40
Now inside of the body here, we just need to define a few things. We need something for this hamburger menu as well as the sidebar
1:45
Now most hamburger menus that you see are going to use a bunch of spans that have some type of class on them like
1:50
this, and it's going to have three spans, one for each different row. but this is really clunky. I like to keep my HTML as clean as possible
1:56
So in our case, what I'm going to do is I'm just going to use a label. And this label, I'm going to give a class here of hamburger menu
2:05
Close off that label. There we go. And then inside this label, I'm going to put a checkbox
2:09
Now, the reason I'm putting a checkbox inside of here is because we're doing this with just CSS
2:14
and we're not using any JavaScript at all. And a checkbox is a great way for us to check if something is currently being clicked
2:20
and to toggle between an open and closed state. Otherwise, you would need JavaScript to do this
2:25
but in our case, we're doing this with just CSS. Now, once that's done, we can just go ahead and create our sidebar
2:30
I'm going to use an aside element for that. I'm just going to give it the class of sidebar
2:34
Make sure I spell this properly. There we go. So now we have an aside, which has the class of sidebar
2:40
The fact that this is an aside doesn't matter. It's just for accessibility purposes. And inside of here, I'm just going to put a nav
2:48
And inside that nav, I'm just going to have a few divs that just say, This is the sidebar
2:57
It doesn't matter what the sidebar content is. All we need is an element with the class of sidebar, and that's all that matters
3:02
And this label with the input is going to take care of everything you can see for our hamburger menu
3:06
So the entire animation, the three lines, and everything else that you can think of, is all taken care of by this one single section right here
3:12
Now what we can do is we can open this up with live servers, so we can actually see what we're working with
3:15
And as you can see, we have our checkbox, and we have our side section that says this at the sidebar
3:19
So now we can finally work on actually styling out what's going on. So instead of our styles.cass, the very first thing that I like to do
3:25
inside of every style seat is I like to get my before, my after, and every element
3:29
So I just like to select essentially everything. And I like to set my box sizing to border box
3:34
If you're unfamiliar what this does, I have a full tutorial covering this and the box model
3:38
I'll link in the cards in description for you. But if we give this a quick save, you notice nothing really happens
3:42
because this is only useful when we start defining things like wits and heights and so on
3:46
So the next thing I want to do is on our body. I'm just going to get rid of any margin. that we have. The reason I want to do that is because I want to make sure our sidebar is pushed
3:53
all the way against the side of our screen, and we need to remove our margin to do that. So now you can see our margin is gone. I can zoom this in a little bit more for you. Now the next thing that I want to
4:00
do is I want to define some CSS variables. If you're unfamiliar with CSS variables, again
4:04
I have a full tutorial on that. I'll link in the cards in description for you. We're going to
4:08
define our root element, and we're just going to define a few to start. So we want to have a bar width
4:13
that's going to be how wide our hamburger bar is going to be. So for now, let's just come in here
4:17
we'll say 60 pixels. We're next going to have a bar height, so we can say bar height, and that's going to be
4:23
eight pixels. And then we also need to have a gap. So we're going to call that hamburger gap, which we're going to set to six pixels as well
4:30
There we go. So now we get that a save. You'll notice nothing changes, and that's just because these are CSS variables that we can
4:35
use later. And these are some of the variables we're going to create where you can change them, and the
4:39
entire rest of the code is just going to work perfectly because it's going to modify based off
4:43
of these different variables. This is why I really like using CSS variables because it means I can say, okay, here's what my width is
4:49
and the rest of my code will just work based on whatever I set this variable to. Now, the next step for us is going to get those three separate lines because as you notice
4:56
we didn't put anything special in our HTML for those lines, so we need to create that essentially from scratch
5:01
And the way I'm going to do that is using a before element and after element as well as this input itself as the elements for our three different lines
5:08
So what we can do is we can come down here and we can select our hamburger. And what did I call this hamburger menu
5:14
Yeah, hamburger menu. And what I want to do is I want to get the before-after element. I also want to select my hamburger menu
5:20
And I want to get the checkbox that's inside of it. That is just our input inside of it
5:24
And I also want to get the after element as well. So this is getting three different things
5:29
First of all, we have our input, which is just that checkbox. Then we have our after and before elements, which are elements we can create
5:34
So if we set here the content to an empty string, that's going to give our before-and-after elements content
5:39
which is going to make them show up on the screen. and then we can actually style what they want to look like
5:44
So we can, for example, set a width here, and our width is our bar width
5:48
So we'll do that. Same exact thing for our height. It's just going to be our height instead of our width for our bar
5:54
The next thing I can do is set some kind of background color So in our case what I want to do is I actually want to define that as a variable So we going to have essentially a foreground and a background variable So we going to say foreground is going to be 333 and background We going to set this to white just like that
6:13
So now I can just say that this is going to be our foreground color. There we go. So now if I save
6:18
you notice, again, our checkbox has been moved out to the side because some of this stuff is starting to show up
6:23
but we still can't quite see anything yet. The reason for this is because, is by default, all these different elements are display in line, and that's because a label
6:30
here is display in line. And we need to modify that to be flex box based because we want to stack these on top of each
6:36
other like we have over here. So what I'm going to do is I'm going to select my overall hamburger menu
6:41
I'm just going to change the display here to flex. Automatically, by doing that, you can now see we have some bars showing up on the right
6:47
hand set of our screen. And if I change the flex direction to column, that's going to stack them on top of each other
6:52
and then I can space them out using this hamburger gap. So I can say the gap is that hamburger gap variable, and that's going to put some space between
6:59
these different elements. I can also come in here and add a border radius. And if I want to have a pill shape, I can just use a large number, like 9,999, and that's
7:07
going to give me some perfectly capped off borders just like that. Now obviously, you notice our input doesn't quite look right because it's still styled
7:14
as a checkbox, so we need to do some extra stuff to make it so that this input looks like we
7:18
want it to. The first thing we can do is we can set the appearance to none. That by default is going to take care of a lot of the workforce, as you can
7:24
see it is removed the default appearance and just replaced to whatever we hard-coded here for our height
7:29
and width. Also, we can remove any pattern and margin that is applied by default, and that's going to
7:34
get our line back into position with the rest of our lines, which is great. And then finally, what we
7:38
can do is we can make sure the outline is set to none, so that way when we actually hover over
7:42
this, as you can see, if I hover over this, you may actually get some kind of outline showing up
7:46
just like that. We don't want that to show up, so I'm going to put the outline set to none, so we
7:49
don't get any weird outline stuff showing up. And I'm also going to come in here, and I'm going to say
7:53
pointer events none, and then just make sure I can't click on this checkbox at all
7:58
Instead, I want all my interactions with the checkbox to be through our label element right here
8:02
And the reason I wrapped my input inside the label is that way when I click on my label
8:07
it'll check and uncheck my checkbox for me. So when I click anywhere inside of this space where my label is, which is just these three
8:13
different lines, then I'll actually check and uncheck my checkbox. I can actually demonstrate that by inspecting the page here
8:19
I'll zoom this in a little bit. And if I look at my input right here, when I click on this, it's actually checking and
8:23
unchecking my input. We can't quite see that, but what I can do inside my code is I can go
8:28
hamburger menu, I can check for the input, and I can check for the checked property, just like that
8:34
and I can just say background is going to be red. So now I can see I'm checking and unchecking
8:40
my checkbox by clicking anywhere inside these three elements, and I can use that checked property
8:44
to animate between my open and closed state instead of just changing the color to red. So for now
8:49
I'll just comment that out. Now the next thing I want to work on is styling out my hamburger menu
8:53
in here I set the background to red. You're going to notice it actually fills the full width of my
8:57
screen. I don't want that. So instead I'm going to set the width to max content. That's just
9:01
going to make it so the width fills up the full space of whatever I have inside of it, which in our case
9:05
is these three different lines. You can remove that background from now since we don't actually need it
9:09
I can go ahead and actually position this where we want it, and I'm going to be using position
9:13
absolute to do that. So I can say position absolute. We can give it a top position and a left
9:17
position. In our case, I'm going to make those both five pixels. So we'll come down here
9:22
a left of five pixels. And now you can see that's showing up right there in the top left-hand
9:25
corner. But our sidebar is now showing up behind it because we positioned this absolutely
9:30
For now, what I'm going to do is I'm just going to comment out the sidebar so it's not there because I want to focus primarily on this hamburger menu first. Now a couple other things I want to do
9:37
I want to set the Z index to some number that's larger than one or zero. So I'm going to set it to
9:42
two here. That way it shows up over top of our sidebar when we start to open and close it
9:45
As you can see here, when I open and close, I want to make sure it shows up over top the sidebar
9:49
The next thing that I want to do inside of here is I want to set my cursor to pointer. That way, when I hover this, I can see that it looks like it's a clickable element, which is great
9:57
And the last thing I want to do is I want to take this top and left position. And I want to actually break it out into a variable
10:02
We're going to call this hamburger margin. I'm going to set it to five pixels
10:07
And then I'll replace both of these with that variable hamburger margin
10:11
Now the main reason that I'm doing that, and let's actually increase this a little bit. Let's make it eight, for example
10:15
There we go. The main reason I'm doing that is so when I open up my sidebar, it actually pushes my content down based on the height of my hamburger menu
10:22
and we need to take into account that top position up there in order to do that
10:26
So now is when we can actually work on the fun part of this. As you can see, when I click on this, I want to do the animation where the middle bar fades out
10:32
and the other two bars essentially become this like X shape. So what we can do in order to do that is we can go down to here where we had this input check section
10:40
So if I just uncomment this, there you go. You can see that whenever it's checked, it's going to be red
10:44
Now we're just changing it to red. Instead, I want to essentially reduce this to a width of zero and make the opacity go down
10:50
to zero as well. So on our input, whenever it is currently checked, we can say our opacity is going to be zero
10:56
and our width is going to be zero. So now you can see that that middle bar is disappearing whenever it is currently checked
11:02
Now I obviously want to animate this, so we're going to make a transition for this instead
11:06
So what I can do up here inside of where I've defined my transition for everything, all my different
11:10
styles, what I can do is I can define a transition. In this transition, I want to transition the opacity property, and I want to transition
11:17
it based on some type of timing function. And I want this to be the same for everything that I animate
11:22
So the sidebar, the actual x being formed, all of that is going to work on the exact same
11:26
timing function. So I'm going to turn that into a variable. I should call it animation timing, just like that
11:31
I can do the exact same thing with my width. I want it to follow the exact same animation timing
11:36
So I'm going to transition both the opacity and the width in our case. So what I can come up here and I can do if I go over into my route
11:43
I can say animation timing and I can define this as like 200 milliseconds ease in out
11:52
So now you can see when I click it's slowly going down to a size of zero and it's fading out
11:56
for us Now to style our x as you can see when I click here the other two turn into an x that going to be quite a bit more complicated both for the selector as well as for the CSS So we can come in here we can say hamburger menu
12:09
and I want to determine if the input is currently checked. Let's actually move this down here
12:13
There we go. So I could come in here and I say input checked, but that's selecting the actual input element
12:18
Instead, I want to select the before element, but I want to only do it when the input is checked
12:23
To do that, we need to use this special has property. So we're saying, does the hamburger menu have an input that's checked inside of it
12:30
If so, then select the before element of our hamburger menu. Now, this has selector is relatively new in CSS, so if you're unfamiliar with it, I have a full video on it
12:38
A link in the cards and description for you. Now, with this done, obviously, we need to do a rotation, so let's rotate this 45 degrees
12:44
and see exactly what this looks like. So if we click, you can see that this has rotated 45 degrees, just like we expect it to
12:50
but obviously it's not quite like we want. It's automatically happening, and it's rotating around the center
12:55
instead of around the left side. As you can see over here, this rotates around the left-hand side point, so that's what we want
13:00
to emulate. So if we go back here, we can actually set a transform origin
13:04
And this transform origin, I want it to be in the left center
13:08
And now if I say, if you can see it rotates around the left-hand side instead of the right-hand side, which is great
13:13
We can do the exact same thing with our after element instead, so we can change this to after
13:17
and we can rotate at the opposite direction. Now you can see we have the beginnings of our X being formed, but obviously it doesn't
13:23
quite look right. So we need a lot of CSS and math to make this look like we want it to
13:27
So in order to figure out how our X should look, we need to figure out how long these lines
13:31
should be. As you can see, these lines start out quite long, but when I click, they shorten
13:35
down the length that they are so that they can fit within the space that we have. And in order
13:39
to figure out what this length should be, we're actually going to use trigonometry. I know that
13:43
sounds super complicated and crazy, but essentially we're just using some really simple math
13:47
in order to do this. So what we need to do is we need to first determine the height of our
13:51
element in order to determine what the length of the diagonal needs to be to fit within that height
13:55
So we're going to come up here and create a brand new variable. We're going to call this hamburger height, and this is going to be the height of our entire hamburger menu
14:03
And this is actually relatively easy to calculate because we have three bars, and we have two
14:07
gaps between those bars. So we know the height is just three times our bar length and two times our gap
14:12
So we can come in here, we can do a calculation. We would take in the height that we have here, which is our bar height
14:18
We know we need to multiply that by three. Looks like I got an extra var in here
14:22
There we go. And then I can just add in the height that we're going to be using for our gap
14:28
So we can say hamburger gap, just like that. Again, it gave me one too many vars
14:32
We want to multiply this by two because there are two total gaps and there are three total bars worth of height
14:37
That right there is going to give us the total height of our container. And then we can determine what the actual width of our bars are going to be
14:43
Now, in order to do that, I'm going to put a menu or a variable inside of our hamburger menu
14:47
and we're going to call this the X width. So it's the width of our bars when we're in the X shape
14:52
This is going to be a calculation, which is going to be based on that hamburger height
14:56
and in order to get the length of the diagonal using trigonometry, all we need to do is multiply this by the square root of two
15:02
because we're using a right angle here. So since we're using a right angle
15:05
we can just multiply by this variable, which is just the square root of two. You can write this out yourself or just Google square root of two
15:11
and it'll give you a variable for the square root of two. If you multiply your height by that variable
15:15
it'll give you the length right here that we need to use. And again, that's because we're using the right angle triangle here
15:21
Now, I know this part may have been a little confusing with the math, but just know all we've done is we've just written some map out
15:26
that this X width variable will just calculate what the width of our actual line
15:30
need to be, so it's not quite so long. Now we can do down here, we can say that our width is going to be that X width variable
15:38
just like that. So now if I save on both of these, you'll notice immediately that this looks a lot more like an X
15:43
It's still not quite perfect, but it's getting there. The only other thing we do is just make sure that we do a little bit of an offset, because
15:49
we're doing currently our rotation around the left center sides. So based on the height of our actual bar, we need to make sure we offset our element a little
15:57
bit just because of the way that we're rotating. Because in a normal triangle, you don't have the width of a bar, you know, a line that
16:02
you're working with, you're working with essentially infinitely thin lines, and that's why everything works super cleanly
16:07
But in our case, we have this thick bar that we need to account for, so we need to essentially offset our element up and down based on the width or the height of our bar
16:14
So to do that, we can come in here and we can actually do a translate. And we want to translate the x position by 0, so we can put 0 here, but we want to translate
16:22
the y position by essentially half of the height of the bar. So I can come in here with a calculation where I get my bar height, and I could just divide
16:30
that by 2. And in our case, this before element, we want to move up, so I'll divide by negative 2
16:35
I'm going to do the exact same thing down here, but I'm going to divide by just 2. And now if I save, you'll see that now our X actually looks really good, and we can animate
16:42
between both of these different elements. So to quickly recap what we did, we calculated the length of our X line
16:48
based on some trigonometry, based on the height, and we know that this is a 45 degree angle
16:52
because we're rotating here by 45 degrees, we know it's a 90 degree triangle and so on
16:56
so we know exactly what that line length of square root of 2 needs to be, do that multiplication
17:01
and then since we actually have a line that's greater than, you know, zero pixels wide, we just need to offset by half of that line's size
17:07
in order to make sure everything lines up perfectly. Now, the next thing I want to do is I want to make sure that this actually animates super
17:12
smoothly so we need to add some additional things inside of our transition so we're
17:16
currently doing opacity and we're doing width so i want to copy this down for a few more
17:20
things because we need to do the rotate let me copy and rotate and we have a translate that we need to
17:25
do as well so now if i save you can see that this is perfectly smoothly animating which is great
17:30
now while we're making these modifications you notice on this example the color actually changes
17:34
so i want to make sure that i animate that as well so i'll just come in here with our background
17:38
color, and I'll make sure that that will animate super smoothly as well
17:43
And that's all we need to do for our transition here. Now the next thing we can work on since we have our fully animated X
17:48
is making sure that it works if we change our numbers. So let's say I change our bar height to 18, and I click
17:53
you can see our X still perfectly forms. So it looks like no matter what our values are our X is going to work exactly like we wanted to So let actually go ahead and make our sidebar do what we want Let add it back in and let make sure we can animate it in and out So we scroll all the way to the bottom here I going to select our sidebar And all I want to do by default is I just want
18:10
to translate this negative 100%, and that's just going to hide it off the edge of our screen just like
18:16
that. Now for now, I'm going to uncomment this just so we can actually see our sidebar. But the next thing
18:21
we need to do is move our sidebar down below our actual menu. So we can put some margin on the top
18:25
to do this. This is going to be a calculation based on some variables. So we actually know the height
18:30
of our hamburger menu, just like that. And then we can add in the margin that we calculated. That's
18:34
just this padding at the top here that we put at the top. So we can come in here, and we can say
18:39
that we have our hamburger margin. We can add into the top there as well. And then we can just
18:43
put in some spacing amount, like one REM, and that'll just give us one REM a space below. If we
18:47
remove that, you can see it's bunched up right next to it. We don't quite want that, so we're just going to give it a little bit of space. So that right there is already putting our sidebar in
18:54
the right location. Now the next thing we need to do is give it some styles, so it's like some background, some padding, and so on. So let's come in here with the background color. We can
19:02
use our variables for this. And in our case, I'm going to be using the foreground variable
19:06
color. And the reason for that is because I want this to be that darker color. It kind of like
19:10
is the opposite of our normal background color. And the color here is going to be our background
19:15
color that we've defined. And that's again because this is the inverse of our normal website
19:18
colors. Now I don't want the sidebar to fill the full width. So I'm going to give it a max
19:22
with. In our case, I'm going to call this 10 REM. There we go. Just to give it a maximum size
19:29
that it can be. And that way, no matter what size our screen is, it's always only taking up a certain
19:33
amount of space. Also, I want to change the height here to be a little bit better. So we can come
19:37
in here with a height, and I want to make this 100BH. There we go. That's going to fill 100
19:44
of the height. But you'll notice we have a little bit of a scroll here. So instead of my margin on the top, I want to set this as padding, and that should hopefully take care of that
19:51
problem for us. As you can see, it removed our scroll bar, which is great. Our bar right here for
19:56
our actual X is still there, but we can't see it because it's the same color as our background
19:59
We'll fix that in a little bit. Also, I want to come in here and I actually want to set this as a minimum height. That way, if our sidebar needs to scroll, it can scroll. Next thing I want to do
20:07
is specify the rest of the padding for our element. So I'm going to make sure I do this before my padding top. I'm going to say we have 0.5 REM and 1RAM of padding. So we have a lot of padding
20:15
on the right and the left and not quite as much on the top and bottom. Then finally, what I want to do
20:19
So I can add this translate back in, and I want to add a transition on that. So we'll say transition here
20:25
Whoops. Transition is going to be on the translate property. And we want to use that same timing we've been using for everything else, that animation timing
20:33
So right now it is hidden by default. But if we have a hamburger menu that has an input that is checked, this is some code we've already talked about before
20:42
then what I want to do is I want to select the sidebar directly after it. That's what this plus button does right here
20:46
Now we've covered quite a few complex selectors in this video. this plus selector and this has selector
20:51
And if you want to learn everything you need to know about CSS selectors, I have a completely
20:55
free cheat sheet you can download. It's going to be linked in the description of this video and it's going to cover all the
20:59
CSS selectors you need to know, such as checked and this plus icon and all the other
21:03
things you can think of like before and after, all those are going to be covered for you
21:06
So inside of here, all we need to do is just set our translate property to zero
21:10
That's just going to reset us. So now when I click on this, you can see that the sidebar is animating in and out
21:15
The last thing we have left is to worry about colors as well as accessibility
21:19
So the colors are going to be relatively straightforward. What I can do is I can just check that when our hamburger menu has an input that is checked
21:29
what I want to do is I just want to swap my colors. So the foreground here, foreground is going to be set to that white color, and our background
21:39
is going to be set to that darker black color. So now when I click, you can see that my X has perfectly transferred its colors, and it's doing
21:46
that all because of right here. We're changing our foreground and back. background color, essentially swapping the two
21:51
And the last thing we need to do is deal with accessibility because if someone can't see
21:54
or they use the keyboard to navigate, we want to make sure that when they are actually navigated
21:58
onto this, that you can see that we have some type of animation showing up or some type of
22:02
highlighting showing up showing that it is actually currently selected. And to do this is actually quite easy
22:08
What we can do is we can select our hamburger menu and we want to check to see if it has
22:12
an input that has a focus of visible. That just means that currently you are tabbed onto something, but it doesn't count when
22:19
you click on it because we don't really need those tiles to show up when we just click on this. So if we currently have a focus that is visible based on tabbing onto it
22:26
then we can get the before element, we can do the exact same thing for our after element
22:30
and we can do the exact same thing for selecting our actual input, just like this
22:34
This is going to select our input, our before, and our after element, whenever we are focused on our input
22:40
so whenever we're tabbed onto our checkbox, and what I want to do is I want to set a border that is going to be one pixel
22:45
and it's going to be the exact same color as our background. So essentially it's not even going to show up
22:49
So if I save and I actually tab onto this in our example here, you can see that we have that one pixel border showing up, but it's the exact same color as the background, so it's really hard to see
22:58
When the color is white here, you can see that you really can't see anything at all other than that a little bit of size is removed just because of the way that widths and heights and stuff work with borders
23:06
But what we can do on top of this is add a box shadow and make it work like a second border
23:11
To do that, we can set zeros for every single thing except for the fourth property
23:15
And this will be the width of our border. In our case, we're going to make this another one pixel wide border
23:19
And we're going to set this to our foreground color. So this color is going to match the color of our actual lines
23:25
So now, you can see if I tab onto this, that this color has given us essentially a white outline
23:30
and then we just have this black section here that is showing up. So our border is that black section, and then the white outline is our actual box shadow
23:36
And here, it's reversed. Our box shadow is black while our border is white. And that gives us this really nice outline effect that I think is really easy and clear to see for someone that can't actually see very well
23:45
and relies on keyboard shortcuts to navigate. And that's all there is to creating this hamburger menu
23:51
If you enjoyed this video and really want to dive further into all the different CSS selectors we used
23:55
I highly recommend checking out my completely free CSS selector Cheechy. It's going to be linked down in the description for you
24:01
With that said, thank you very much for watching and have a good day