Mastering JavaScript: 30 Hands-on Projects for Beginners (Project Series 4/30)
Understanding JavaScript fundamentals by building a Navbar Toggle for a Website
Credits
Special credit goes to John Smilger for using his projects in this article series.
Introduction
Welcome to Article No.4 in the project series "Mastering JavaScript: 30 Hands-on Projects." In the third article, we built a Simple Reviews Slider that allowed a user to navigate through different reviews and see the details of each review.
This article series aims to build your mastery of JavaScript by building 30 simple projects. After building these projects, you'll feel confident enough to pick up any JavaScript framework.
Today, we'll be building Project 4 of the Project Series and we'll be working on a Navigation Toggle for a Website.
Project 3: Navigation Toggle
Working Project:
The goal of this project is to allow a user to use the navigation toggle button to show and hide the navigation links. The interesting part is that some of the JavaScript concepts that were applied in the last project will also be used here, which means we are building on what you already know, which is a great way to learn Javascript.
New JavaScript concepts that'll be applied:
Condition Statements
DOM Manipulation
Event Listeners
If you're still not very conversant with these concepts, I've added links to tutorials in the resources section of the article to bring you up to speed. You can read about them before you start this project.
I have also provided the HTML and CSS codes which you can copy to your local machine so we can only focus on explaining the JavaScript logic.
HTML Codes:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Navbar</title>
<!-- font-awesome -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"
/>
<!-- styles -->
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<nav>
<div class="nav-center">
<!--nav header-->
<div class="nav-header">
<i class="fas fa-2x fa-torah"></i>
<button class="nav-toggle">
<i class="fas fa-bars"></i>
</button>
</div>
<!-- links -->
<ul class="links">
<li>
<a href="index.html">home</a>
</li>
<li>
<a href="about.html">about</a>
</li>
<li>
<a href="projects.html">projects</a>
</li>
<li>
<a href="contact.html">contact</a>
</li>
</ul>
<!-- social media -->
<ul class="social-icons">
<li>
<a href="https://www.twitter.com">
<i class="fab fa-facebook"></i>
</a>
</li>
<li>
<a href="https://www.twitter.com">
<i class="fab fa-twitter"></i>
</a>
</li>
<li>
<a href="https://www.twitter.com">
<i class="fab fa-behance"></i>
</a>
</li>
<li>
<a href="https://www.twitter.com">
<i class="fab fa-linkedin"></i>
</a>
</li>
<li>
<a href="https://www.twitter.com">
<i class="fab fa-sketch"></i>
</a>
</li>
</ul>
</div>
</nav>
<!-- javascript -->
<script src="app.js"></script>
</body>
</html>
CSS Codes:
/*
===============
Fonts
===============
*/
@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap');
/*
===============
Variables
===============
*/
:root {
/* dark shades of primary color*/
--clr-primary-1: hsl(205, 86%, 17%);
--clr-primary-2: hsl(205, 77%, 27%);
--clr-primary-3: hsl(205, 72%, 37%);
--clr-primary-4: hsl(205, 63%, 48%);
/* primary/main color */
--clr-primary-5: hsl(205, 78%, 60%);
/* lighter shades of primary color */
--clr-primary-6: hsl(205, 89%, 70%);
--clr-primary-7: hsl(205, 90%, 76%);
--clr-primary-8: hsl(205, 86%, 81%);
--clr-primary-9: hsl(205, 90%, 88%);
--clr-primary-10: hsl(205, 100%, 96%);
/* darkest grey - used for headings */
--clr-grey-1: hsl(209, 61%, 16%);
--clr-grey-2: hsl(211, 39%, 23%);
--clr-grey-3: hsl(209, 34%, 30%);
--clr-grey-4: hsl(209, 28%, 39%);
/* grey used for paragraphs */
--clr-grey-5: hsl(210, 22%, 49%);
--clr-grey-6: hsl(209, 23%, 60%);
--clr-grey-7: hsl(211, 27%, 70%);
--clr-grey-8: hsl(210, 31%, 80%);
--clr-grey-9: hsl(212, 33%, 89%);
--clr-grey-10: hsl(210, 36%, 96%);
--clr-white: #fff;
--clr-red-dark: hsl(360, 67%, 44%);
--clr-red-light: hsl(360, 71%, 66%);
--clr-green-dark: hsl(125, 67%, 44%);
--clr-green-light: hsl(125, 71%, 66%);
--clr-black: #222;
--ff-primary: 'Roboto', sans-serif;
--ff-secondary: 'Open Sans', sans-serif;
--transition: all 0.3s linear;
--spacing: 0.1rem;
--radius: 0.25rem;
--light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
--dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
--max-width: 1170px;
--fixed-width: 620px;
}
/*
===============
Global Styles
===============
*/
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--ff-secondary);
background: var(--clr-grey-10);
color: var(--clr-grey-1);
line-height: 1.5;
font-size: 0.875rem;
}
ul {
list-style-type: none;
}
a {
text-decoration: none;
}
h1,
h2,
h3,
h4 {
letter-spacing: var(--spacing);
text-transform: capitalize;
line-height: 1.25;
margin-bottom: 0.75rem;
font-family: var(--ff-primary);
}
h1 {
font-size: 3rem;
}
h2 {
font-size: 2rem;
}
h3 {
font-size: 1.25rem;
}
h4 {
font-size: 0.875rem;
}
p {
margin-bottom: 1.25rem;
color: var(--clr-grey-5);
}
@media screen and (min-width: 800px) {
h1 {
font-size: 4rem;
}
h2 {
font-size: 2.5rem;
}
h3 {
font-size: 1.75rem;
}
h4 {
font-size: 1rem;
}
body {
font-size: 1rem;
}
h1,
h2,
h3,
h4 {
line-height: 1;
}
}
/* global classes */
/* section */
.section {
padding: 5rem 0;
}
.section-center {
width: 90vw;
margin: 0 auto;
max-width: 1170px;
}
@media screen and (min-width: 992px) {
.section-center {
width: 95vw;
}
}
main {
min-height: 100vh;
display: grid;
place-items: center;
}
/*
===============
Navbar
===============
*/
nav {
background: var(--clr-white);
box-shadow: var(--light-shadow);
}
.nav-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
}
.nav-toggle {
font-size: 1.5rem;
color: var(--clr-primary-5);
background: transparent;
border-color: transparent;
transition: var(--transition);
cursor: pointer;
}
.nav-toggle:hover {
color: var(--clr-primary-1);
transform: rotate(90deg);
}
.logo {
height: 40px;
}
.links a {
color: var(--clr-grey-3);
font-size: 1rem;
text-transform: capitalize;
letter-spacing: var(--spacing);
display: block;
padding: 0.5rem 1rem;
transition: var(--transition);
}
.links a:hover {
background: var(--clr-primary-8);
color: var(--clr-primary-5);
padding-left: 1.5rem;
}
.social-icons {
display: none;
}
/* BY DEFAULT HIDE LINKS*/
.links {
height: 0;
overflow: hidden;
transition: var(--transition);
}
/* TOGGLE CLASS */
.show-links {
height: 10rem;
}
@media screen and (min-width: 800px) {
.nav-center {
max-width: 1170px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
}
.nav-header {
padding: 0;
}
.nav-toggle {
display: none;
}
.links {
height: auto;
display: flex;
}
.links a {
padding: 0;
margin: 0 0.5rem;
}
.links a:hover {
padding: 0;
background: transparent;
}
.social-icons {
display: flex;
}
.social-icons a {
margin: 0 0.5rem;
color: var(--clr-primary-5);
transition: var(--transition);
}
.social-icons a:hover {
color: var(--clr-primary-7);
}
}
Remember that the Javascript logic we are about to write should be written in app.js
folder of the project.
You should also resize the page to the mobile size so you can see the navbar toggle take effect.
The JavaScript Logic:
Looking at the HTML and CSS, the height of the navbar which is the .links
class is 0px by default.
/* BY DEFAULT HIDE LINKS*/
.links {
height: 0;
overflow: hidden;
transition: var(--transition);
}
/* TOGGLE CLASS */
.show-links {
height: 10rem;
}
I also have written styles for a .show-links
class in the CSS so that the height of the navbar will expand to 10rems or 160px when the button with the .nav-toggle
class is clicked.
We can achieve this in two ways:
Using the conditional statement
Using the toggle method.
Using Conditional Statement
Grab hold of the DOMs
const navToggle = document.querySelector('.nav-toggle'); const links = document.querySelector('.links');
Add an event listener to the navToggle button
navToggle.addEventListener('click', () => { //codes });
Use a conditional statement to check if the "links" element has a class of "
show-links
" using the.contains()
method. If it does, the class is removed using the .remove() method. If it does not, the class is added using the .add() method.The
.classList
property is a property of an Element that returns a live collection of the classes applied to that element.The classList property provides several methods to manipulate the class list of an element, such as:
.add()
- adds one or more classes to an element.remove()
- removes one or more classes from an element.toggle()
- toggles one or more classes (adds if not present, removes if present).contains()
- checks if an element has a specific class.item()
- returns the class at a specified index in the class list
const navToggle = document.querySelector('.nav-toggle');
const links = document.querySelector('.links');
navToggle.addEventListener('click', () => {
if (links.classList.contains('show-links')) {
links.classList.remove('show-links')
}
else {
links.classList.add('show-links');
}
});
This effectively toggles the "show-links" class on and off when the "nav-toggle" element is clicked.
Using a Toggle Method
Instead of using an if-else statement, we can also use the toggle method to apply and un-apply the .show-links
class.
const navToggle = document.querySelector('.nav-toggle');
const links = document.querySelector('.links');
navToggle.addEventListener('click', () => {
links.classList.toggle('show-links')
});
When the navToggle
element is clicked, it will check if the links
element has the "show-links" class, if it does it will remove the class otherwise it will add the class.
And we're done!
Short and sweet, init?
Conclusion
In this article, we created a functional navigation toggle using two approaches: an if-else statement and a toggle method. When the toggle button is clicked, it displays the navigation links if it was previously hidden and vice-versa. This project is a basic example of creating a dynamic and interactive feature with JavaScript.
This project can be a good starting point for more advanced projects and will help you build a solid foundation in JavaScript. With the knowledge gained from this article, you can build more complex projects and take your skills to the next level.
Watch out for Project 5/30 soon. Thanks for reading!
Resources
DOM Manipulation: The code uses JavaScript to manipulate the DOM elements and update the review information displayed on the page. To learn more about DOM manipulation, you can refer to this tutorial: w3schools.com/js/js_htmldom.asp
Event Listeners: The code uses event listeners to listen for clicks on the next, prev, and random buttons, and updates the review information accordingly. To learn more about event listeners, you can refer to this tutorial: w3schools.com/js/js_events.asp
Conditional Statements: The code uses if-else statements to check if the current review is the first or last item in the reviews array, and updates the currentItem variable accordingly. To learn more about conditional statements in JavaScript, you can refer to this tutorial: w3schools.com/js/js_if_else.asp
Please note that some of the tutorials may not cover all the concepts I listed, but it is a good place to start.