Project: Off-canvas menu
In this lesson, we will create an off-canvas menu in javascript.
So, what is an off-canvas menu?
It is nothing but a secret menu that is positioned outside of the visible portion of the screen.
And when the menu button is clicked, the off-canvas content will be pushed into the visible portion of the screen.
And when the menu button is clicked again, it will be pushed off the screen so that it becomes hidden again.
Usually, the Off-canvas pattern is implemented for mobile devices to save some screen space and keep things organized.
But sometimes, it is used for serving desktop users as well.
It is totally a design preference.
Anyway, let's quickly implement it.
The starter files
Download the project starter files and open the project inside your code editor.
And here is the project structure:
.
└── ai-art-starting-files/
├── images/
│ ├── bars-solid.svg
│ ├── open-theatre.png
│ ├── watering-robot.png
│ └── ...
├── index.html
├── style.css
└── index.js
The HTML
If you open up the index.html
file, it already has the HTML markup for implementing the off-canvas functionality.
<body>
<div id="off-canvas-content">
<!-- ... -->
</div>
<div id="page-content">
<button class="menu-toggle">
<!-- ... -->
</button>
<div id="main-content">
<!-- ... -->
</div>
</div>
<script src="index.js"></script>
</body>
If you notice, the <body>
element has two elements.
#off-canvas-content
element that holds the off-canvas menu#page-content
element that holds the content of the page with the menu button
The CSS
The style.css
file contains the basic styling for the #page-content
only.
The initial preview
If you notice, the #off-canvas-content
element is not styled at all.
Also, it must be positioned outside the visible screen, right?
So, let's style it and position it off the screen
#off-canvas-content{
width:20rem;
background-color:#E2F1F8;
padding:40px;
position:absolute;
left:-20rem;
top:0;
bottom:0;
box-sizing: border-box;
transition: all 0.3s ease-in;
}
nav ul, nav li{
list-style: none;
padding:0;
margin:0;
}
nav li{
margin-bottom:10px;
}
nav a{
text-decoration: none;
}
Add the above CSS to the end of the style.css
file.
Apart from some basic list styling, it is basically making the #off-canvas-content
positioned absolutely so that it can be pushed off the screen using left:-20rem
.
Everything is now set.
But when we click on the menu button, nothing happens.
Our goal
- When the menu button is clicked, the off-canvas content should be pushed into the visible portion of the screen.
- And then when the button is clicked again, the off-canvas content should be pushed off the visible portion of the screen.
And here is the javascript that helps achieve our goal:
//Select the Menu button
const menuToggleButton = document.querySelector(".menu-toggle");
//Add event listener to it
menuToggleButton.addEventListener("click", function(){
document.body.classList.toggle("off-canvas-is-open");
});
Add it to the end of the index.js
file.
You already know what's happening here.
First, we are selecting the menu button and then we are adding a click
event listener to it.
And every time the menu button is clicked, we are toggling the class "off-canvas-is-open"
on the <body>
element.
<body>
element using the querySelector()
method. You can directly access it using the document.body
. This facility is only applicable to the <body>
element.document.body.classList.toggle("off-canvas-is-open");
Anyway, the idea here is:
- When the class
"off-canvas-is-open"
is added to the<body>
element, the off-canvas content should be pushed inside the screen. - When we remove the class, the off-canvas content should be pushed off the screen again.
And, here is the supporting CSS that pushes the #off-canvas-content
into the screen when the "off-canvas-is-open"
class is added to the <body>
element:
.off-canvas-is-open #off-canvas-content,
.off-canvas-is-open #page-content{
transform: translateX(20rem);
}
Using the transform
property is the easiest way to push the HTML elements.
Add it to the end of the style.css
file.
If you now, open up the browser, you should the functionality working as expected:
Just to be on the same page, here is how everything works together
The initial state
When the index.html
is initially loaded, the class "off-canvas-is-open"
is not present on the <body>
, tag.
So, the #off-canvas-content
stays outside the screen.
But when the button was clicked for the first time
The class "off-canvas-is-open"
will be added to the <body>
element.
And it will trigger the following CSS:
.off-canvas-is-open #off-canvas-content,
.off-canvas-is-open #page-content{
transform: translateX(20rem);
}
This results in the following:
- Off-canvas content is being pushed into the visible portion of the screen.
- The page content will be pushed slightly, too.
Finally, when the button clicked again...
The class "off-canvas-is-open"
will be removed from the <body>
element using Javascript:
menuToggleButton.addEventListener("click", function(){
document.body.classList.toggle("off-canvas-is-open");
});
It makes the following CSS no longer applicable:
.off-canvas-is-open #off-canvas-content,
.off-canvas-is-open #page-content{
transform: translateX(20rem);
}
So, this results in the following:
- Off-canvas content is being pushed outside of the visible portion of the screen.
- The page content will be pushed back to its original position.
That's all.
Easy, right?
In the next lesson, we will learn about passing parameters to custom functions.