CodeNewbie Community 🌱

Cover image for Coding my portfolio: Building a 🍔 hamburger menu w/ HTML & CSS
McKenna Bramble
McKenna Bramble

Posted on

Coding my portfolio: Building a 🍔 hamburger menu w/ HTML & CSS

✨ Hello! ✨

In this series, I am documenting the process of building my portfolio website. Thank you for reading!

🍔 The Hamburger Menu

A hamburger menu is simply a button that, when selected, will display a navigation menu. It is usually in the upper right or left corner of mobile apps and often looks like three lines stacked on top of one another. Here is an example, which also happens to be my navigation bar for my mobile and tablet portfolio designs:

A screenshot of a mobile navigation bar. On the left are the words "McKenna Bramble" and on the right is an icon made up of three different colored bars stacked on top of one another.

Once the multi-colored hamburger is clicked or tapped, it will open the navigation menu shown below:

A screenshot of a mobile navigation menu. At the top is a navigation bar with the words "McKenna Bramble" in the upper left corner and an "x" icon in the upper right corner. There are three buttons in the center of the screenshot titled "about," "projects," and "connect."

There are several ways to build a menu like this, but I will be utilizing an invisible checkbox to show the menu when it is selected and hide it when it is unselected.

📢📢📢 Before jumping into the code, I wanted to shout out this Navbar CodePen by @alvarotrigo. I used this as a jumping off point for my hamburger menu and it was extremely helpful!

🧱 Writing the HTML

Below is the HTML for the hamburger menu:

Inside of the <nav> element you will see the following tags:

1. <input class="checkbox"/>
<input
  class="checkbox"
  type="checkbox"
  name="hamburger-menu"
  id="hamburger-menu"
/>
Enter fullscreen mode Exit fullscreen mode

This checkbox will be what the user clicks or taps to toggle the menu. It will be in the same location as the three lines that make up <div class="hamburger-menu">.

2. <div class="logo"> & <div class="hamburger-menu">
 <div class="logo">
   <h1>McKenna Bramble</h1>
 </div>

 <div class="hamburger-menu">
   <span class="line line1"></span>
   <span class="line line2"></span>
   <span class="line line3"></span>
 </div>
Enter fullscreen mode Exit fullscreen mode

The code above represents the navigation bar, pictured below:
A screenshot of a mobile navigation bar. On the left are the words "McKenna Bramble" and on the right is an icon made up of three different colored bars stacked on top of one another.

3. <div class="menu-list">
<div class="menu-list">
  <div class="about-container">
    <li class="about"><a href="#">about</a></li>
  </div>

  <div class="projects-container">
    <li class="projects"><a href="#">projects</a></li>
  </div>

  <div class="connect-container">
    <li class="connect"><a href="#">connect</a></li>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

<div class="menu-list"> represents the list of menu options that appears when the hamburger menu button is toggled, pictured below:

A screenshot of a mobile navigation menu. At the top is a navigation bar with the words "McKenna Bramble" in the upper left corner and an "x" icon in the upper right corner. There are three buttons in the center of the screenshot titled "about," "projects," and "connect."

🎨 Applying CSS styles

Below is the CSS for the hamburger menu:

There is a lot of CSS here, but I want to highlight a few important things when it comes to adding styles for a hamburger menu:

1. Styling the .checkbox class
.checkbox {
  height: 40px;
  width: 40px;
  position: absolute;
  top: 35px;
  right: -5px;
  z-index: 5;
  opacity: 0;
  cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

First, we need to define the area of the checkbox. I set the height and width both to 40px.

Setting the position property to absolute will remove the checkbox and the space it took up in the page layout from the document flow.

A screenshot of the navigation bar. The checkbox has changed its location to the top left corner of the navigation bar.

Now that the position property is set, we can use the top and right properties to move the checkbox into its final position in line with the hamburger menu button.

A screenshot of the navigation bar. There is an arrow indicating that the checkbox needs to be moved from the left to the right of the navigation bar.

I set the top property to 35px from the top of its parent element (the "nav-container" div) and the right property to -5px away from the right of the parent element. The result is a properly positioned checkbox, pictured below:

A screenshot of the navigation bar. The checkbox element is overlaying the three lines that make up the hamburger button menu.

From here, we need to make sure that the checkbox element stacks on top of the three hamburger lines instead of underneath. Assigning a value to the z-index property of a positioned element will adjust how it stacks with other elements. Elements with a larger z-index will stack on top of those with smaller z-indexes.

Right now, the three lines that make up the .hamburger-menu div are stacked on top of the .checkbox, making it more difficult for a user to toggle the menu. Setting the z-index property of the .checkbox to z-index: 5 and the .hamburger-menu to z-index: 2 ensures that the .checkbox stacks on top of the three .hamburger-menu lines.

Finally, setting the .checkbox opacity to opacity: 0 will make the checkbox invisible.

A screenshot of a mobile navigation bar. On the left are the words "McKenna Bramble" and on the right is an icon made up of three different colored bars stacked on top of one another.

2. Styling the menu-list class
.menu-list {
  display: flex;
  flex-direction: column;
  text-align: center;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 80vh;
  opacity: 0;
  overflow: hidden;
  padding: 0;
}
Enter fullscreen mode Exit fullscreen mode

Setting the opacity to opacity: 0 hides the .menu-list from view. We will be adjusting the opacity later when applying the animation styles.

🪄 Applying animation styles

1. transition & opacity

I will be using the transition CSS property to increase the opacity of the .menu-list to 100% when the checkbox is checked. I will also use this property to reduce the opacity of the .logo h1 to 0.

Below is the code that will make "McKenna Bramble" disappear when the checkbox is checked:

.nav-container input[type="checkbox"]:checked ~ .logo h1 {
  opacity: 0;
  transition: opacity 1s;
}
Enter fullscreen mode Exit fullscreen mode

:checked is a pseudo-class that is used for radio and checkbox inputs. Adding the :checked selector to .nav-container input[type="checkbox"] means that the properties inside of the curly braces will only be applied when that specific checkbox is checked. Anything after ~ indicates the element(s) to which the properties are being applied. So the code above is saying that when the checkbox is checked, the opacity of .logo h1 will be changed to 0.

Using the transition property will control how long it takes for the opacity of .logo h1 to change from 100% to 0. The syntax in this case for the transition property is transition: <property> <duration>. So transition: opacity 1s means that the opacity property will change over the duration of 1s (one second).

The same logic is used to increase the opacity of the .menu-list to 100%:

.nav-container input[type="checkbox"]:checked ~ .menu-list {
  opacity: 100%;
  transition: opacity 2s;
}
Enter fullscreen mode Exit fullscreen mode
2. The transform & transform-origin properties

The transform property allows you to modify an element by rotating, skewing, scaling, or translating it. I will be using it to rotate and scale the three .hamburger-menu lines. When checked, the lines will transform from a stack of three to an "x" shape, as pictured below:

The left side of the image shows three differently colored lines stacked on top one another. The right side of the image shows two of those same lines transformed into an "x." There is an arrow pointing from the left set of lines to the right set of lines to indicate the transformation.

To achieve this transformation, each line will have a transform property applied when the checkbox is checked. Additionally, each line will have a transition property that defines how the transform property is applied:

Line 1.
a. .line1 will rotate 44 degrees:

.nav-container input[type="checkbox"]:checked ~ .hamburger-menu .line1 {
  transform: rotate(44deg);
}
Enter fullscreen mode Exit fullscreen mode

b. It will take 0.4s (0.4 seconds) for .line1 to rotate 44 degrees and ease-in-out means that the transition effect will have a slow start and slow end:

.line1 {
  transition: transform 0.4s ease-in-out;
  background: #f7a565;
}
Enter fullscreen mode Exit fullscreen mode

c. Both .line1 and .line3 need a transform-origin, which defines the point around which an element rotates. The default transform-origin is center, so we will need to adjust this:

.line1 {
  transform-origin: 0% 0%;
  transition: transform 0.4s ease-in-out;
  background: #f7a565;
}
Enter fullscreen mode Exit fullscreen mode

Setting the transform-origin to 0% 0% means that the element will rotate around the left top of the .line1 element:

A screenshot of three lines stacked on top of one another. There is an arrow pointing to the left top corner of the line one element, indicating the transform-origin. There is another arrow pointing at the left bottom corner of the bottom line, indicating the transform-origin of the line three element.

Line 2.
a. The scaleY() function will be used to resize .line2 along the vertical y-axis. Setting the function to transform: scaleY(0) will effectively make the line "disappear:"

.nav-container input[type="checkbox"]:checked ~ .hamburger-menu .line2 {
  transform: scaleY(0);
}
Enter fullscreen mode Exit fullscreen mode

MDN Web Docs has a demo you can play with to see how inputting different integers in the scaleY() function will affect an element.

b. .line2 also has a transition property that sets the duration and timing of the transformation:

.line2 {
  transition: transform 0.2s ease-in-out;
  background: #f4ce4b;
}
Enter fullscreen mode Exit fullscreen mode

Line 3.
a. .line3 will rotate -44 degrees:

.nav-container input[type="checkbox"]:checked ~ .hamburger-menu .line3 {
  transform: rotate(-44deg);
}
Enter fullscreen mode Exit fullscreen mode

b. .line3 will have transform-origin and transition properties similar to .line1:

.line3 {
  transform-origin: 0% 100%;
  transition: transform 0.4s ease-in-out;
  background: #51c492;
}
Enter fullscreen mode Exit fullscreen mode

Setting the transform-origin to 0% 100% means that the element will rotate around the left bottom of the .line3 element:

A screenshot of three lines stacked on top of one another. There is an arrow pointing to the left top corner of the line one element, indicating the transform-origin. There is another arrow pointing at the left bottom corner of the bottom line, indicating the transform-origin of the line three element.

🥳 Final Thoughts

I love all of the cool and intricate things that can be achieved with only HTML and CSS. Thank you for following along my portfolio-building process!

Top comments (1)

Collapse
 
taurist profile image
Tauri StClaire

Thank you so much for your amazing walkthrough with lots of pictures and explanations! I will also be inserting a dropdown into my current project and have never done one so this is super helpful!!