In this article, I'll be explaining how to create the Hamburger Menu Icon as simply as possible, for web pages on mobile devices with HTML, CSS and Javascript without having to import icons or classes from external stylesheets.
Pre-requisites
You would need to have a basic idea of how to markup with HTML.
You would need to have an idea of how CSS Media Queries work and how CSS selectors are combined to style elements.
You would also need a basic understanding of variable declaration in Javascript along with how to traverse the DOM.
If you are already comfortable with them, then let's head right in and create our Hamburger ๐.
We would be starting with the HTML code
<nav>
<h2 class = "logo">AirPeak!</h2>
<button class = "hamburger">
<span class = "line-1"><span>
<span class = "line-2"><span>
<span class = "line-3"><span>
</button>
<ul class = "nav-ul">
<li><a href = "#">Home</a></li>
<li><a href = "#">Services</a></li>
<li><a href = "#">Contacts</a></li>
<li><a href = "#">About</a></li>
</ul>
</nav>
We are using a nav
tag because the icon when clicked would display a list of tabs that define page navigation. The icon itself would be created by the three span
tags nested within the button
tag so that when we click the button, it unfolds an unordered list (ul
) that contain the tabs.
Note the tags to which we added a class attribute as they would come in handy in styling and in our javascript file.
With just the markup, our webpage would be having this look.
Alright, since we are done with the markup, let's add some styling to it.
The CSS stylings
:root{
--deep-blue: hsl(217, 28%, 15%);
--light-blue: hsl(217, 91%, 70%);
--white: hsl(0, 0%, 100%);
--smoky-white: hsl(0, 0%, 96%);
}
nav{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
padding: 15px;
background-color: var(--deep-blue);
}
nav h2{
color: var(--light-blue);
}
.nav-ul{
display: flex;
justify-content: center;
align-items: center;
padding: 0;
list-style-type: none;
}
.nav-ul li a{
display: inline-block;
color: var(--white);
padding: 10px 20px;
text-decoration: none;
}
.hamburger{
background-color: transparent;
border: none;
cursor: pointer;
display: none;
}
.hamburger:focus{
outline: none;
}
In the first selector, we use CSS variables because we don't want to keep rewriting a long value, so we use a variable to replace it anywhere in the stylesheet.
In the
nav
selector, we use the display flex to put the whole navigation tab in a row, we justified the content to space-between and setting flex-wrap at wrap would allow for the items to wrap to the next line in the event that one of the items overflows the parent container i.e.nav
tag.In the
.nav-ul
selector, display flex is used again then align-items and justify-content are both set at center with the list-style-type property removing the bullet points that comes with list items of unordered lists.In the
.nav-ul li a
selector, we set the display of each list item to inline-block.In the
.hamburger
class, we set the background colour of the button to transparent and its borders to none. Setting the button to those values would allow it to blend in with the navbar and make its children i.e. the span tags which would be hamburger icon to be seen clearly. Then, we set its display to none as we are on a large screen and do not need to use the icon, this means that in smaller screens is where would want to see it displayed.
This is how our webpage would like after our styling.
The CSS stylings above are for the web page on larger screens. We would then need to add media queries to make the webpage responsive for mobile too.
CSS Media Queries
@media only screen and (max-width: 768px){
.nav-ul{
display: none;
flex-direction: column;
width: 100%;
}
.show{
display: flex;
}
span{
height: 3px;
width: 30px;
border-radius: 3px;
background-color: var(--smoky-white);
display: block;
margin-bottom: 3px;
}
.tr-line-1{
transform: rotate(-45deg) translateY(4px);
}
.tr-line-2{
display: none;
}
.tr-line-3{
transform: rotate(45deg) translateY(-4px);
}
.hamburger{
display: block;
}
}
@media only screen and (max-width: 425px){
nav h2{
font-size: 1.3rem;
}
}
In the CSS codes above, we see that we have two media queries being used; the first one at a viewport max-width of 768px and the second at a viewport max-width of 425px.
The first selector we see is the
.nav-ul
for the list of our tabs, here we hide the display by setting it to none, this means it would not display in the navbar at widths less than 768px. We then set the width to 100% of the viewport so that if we need it displayed it wraps to the next line and its list items would be listed in a column, one on top of each other. because of the flex-direction property.In the next selector, we created a class,
.show
which wasn't originally in the markup file along with the tr-line classes which represent each of the span elements. These classes would come in handy in the javascript file.We then styled the
span
tag in such a way to give it the impression of a harmbuger, by styling each span to a single line and stacking each of them on top the other.Finally, the
.hamburger
class is set to a display of block, remember it was set to none at first because we didn't want it to be seen at larger screens.
When we are done adding the media queries, this is how the webpage would look.
Javascript
const hamburger = document.querySelector('.hamburger');
const navUL = document.querySelector('.nav-ul');
const line1 = document.querySelector('.line-1');
const line2 = document.querySelector('.line-2');
const line3 = document.querySelector('.line-3');
hamburger.addEventListener('click', () => {
navUL.classList.toggle('show');
line1.classList.toggle('tr-line-1');
line2.classList.toggle('tr-line-2');
line3.classList.toggle('tr-line-3');
})
In the javascript file, we first declare the variables by accessing the concerned HTML elements in the DOM tree. After this is done, we then add an event listener to the hamburger class which would mean that we want a particular event to take place whenever we perform an action on the button.
The event listener method takes in two arguments; the first event you have to take and the second, the action that follows the event. In our case, we are using a click event so we are saying that if we on the hamburger button which is now occupied by the icon, we want the activities in the function to be carried out.
So what actions are we expecting?
The function shows that we would toggle those classes we created for the media queries and were not initially in the markup file. Toggling here means that every time we click on the hamburger button, the DOM Tree is scanned and the variables which we attached the 'classList toggle method' to are checked to see if they contain those classes, if they do not contain them, the classes are then added but if they do have them, then the classes are removed. It's like putting a light switch on or off.
- The
.show
class selector has a property of display flex and it would be added to the.nav-ul
class which would formerly had a display of none. This would then give the impression of the unordered list of our tabs unfolding out of our navbar every time we click the hamburger icon, and folding back into the navbar for every second click. - The other classes which have the 'tr-' prefix which stands for translate were created to give the effect of the hamburger icon morphing into an โ for a better user experience. This is done by rotating the top span by -45deg angle and the bottom by rotating the bottom span by 45deg angle whilst the middle span display is removed.
Conclusion
So by simply following these steps, one can easily create a hamburger icon for your mobile webpages without having to fetch something from external stylesheets. We have finally come to the end of our article and I super grateful to see that you stuck with us to the end. I really hope you learnt something new today.
Cheers and see you in the next article.