The off-canvas menu is a popular design pattern used in today’s modern responsive web and app design. It’s a popular alternative to the dropdown menu, especially if you want to display more than navigation links.
To build the off-canvas menu we’ll only use HTML and CSS. That’s right, no JavaScript!
1. Creating the HTML structure
Before we can start working, we need to set-up the project file structure and the basic mark-up.
1.1 Setting up the project
Since we’re going to create different off-canvas menu styles, we’ll use 4 style sheets to define the look of the slide menu. The style.css contains the general rules of the site and to keep an uniform look on all the browsers, we’ll use normalize.css by Nicolas Gallagher.
1.2 Basic HTML
To add some interest to the Off-canvas menu links, we’ll use some icons from Font Awesome.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Off-canvas navigation menu Tutorial"> <meta name="keywords" content="slide-menu, sidebar, off-canvas, menu, navigation" /> <meta name="author" content="AcasA Programming"> <title>Off-canvas navigation menu Tutorial</title> <link rel="stylesheet" type="text/css" href="css/normalize.css" /> <link rel="stylesheet" type="text/css" href="css/style.css" /> <link rel="stylesheet" type="text/css" href="css/slide.css" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> </head> <body> </body> </html> |
2. Building the HTML
The side menu is placed in an aside
tag and the navigation links in the nav
tag. The menu will be toggled by the labels of a hidden checkbox. Since we’re using a checkbox, we don’t need to write a single line of Java Script!
2.1 THe Off-canvas menu HTML
Inside the body
tag place the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<input type="checkbox" id="offcanvas-menu" class="toggle" /> <div class="container"> <aside class="menu-container"> <div class="menu-heading"> <label for="offcanvas-menu" class="close-btn"> <i class="fa fa-times"></i> </label> </div><!--end menu-heading--> <nav class="slide-menu"> <ul> <li><a href="#"><i class="fa fa-home"></i>Home</a></li> <li><a href="#"><i class="fa fa-star"></i>Favorites</a></li> <li><a href="#"><i class="fa fa-folder-open"></i>Categories</a></li> <li><a href="#"><i class="fa fa-cogs"></i>Settings</a></li> </ul> </nav><!--end slide-menu --> </aside><!--end menu-container--> |
We can add a close button in the sidebar to close the menu. We’ll use a label
HTML tag. Note that the label references the input’s id: offcanvas-menu . I used a close icon from Font Awesome to show the close action.
In the nav
we have a collection of links and some icons.
2.2 The site content
Our content is placed in a section
with a class of .content
. In this section we have 2 labels that reference the checkbox input.
The first label has a class of full-screen-close
and is used to close the off-canvas menu by clicking the content. To highlight the menu, we’ll apply a dark overlay on the content.
The .menu
divider holds another label that targets the input checkbox. To show that this label toggles the menu, I used a hamburger icon from Font Awesome.
In the header
I placed the title and a link to the previous AcasA Programming demo and a link to read the article.
The .menu-options
div is used to display the 4 buttons used to switch between various slide menu styles and right or left positions.
In the .content-body
div I used some placeholder text from Fillerati. You can use your own text, some lorem ipsum or other placeholder text from the sites mentioned in our resource list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<section class="content"> <label for="offcanvas-menu" class="full-screen-close"></label> <div class="menu"> <label for="offcanvas-menu" class="toggle-btn"> <i class="fa fa-bars"></i> </label> </div><!--end menu--> <header> <div class="ap-meta"> <a href="#"><i class="fa fa-chevron-left"></i><span>Previous demo<span></a> <a href="#"><i class="fa fa-search"></i><span>Read article on AcasA Programming<span></a> </div> <h1>Off - Canvas Menu Navigation Tutorial</h1> </header> <div class="menu-options clearfix"> <h3>Slide options</h3> <div class="left"> <a href="index.html">Left Side Slide</a> <a href="left-push.html">Left Side Push</a> </div> <div class="right"> <a href="right-slide.html">Right Side Slide</a> <a href="right-push.html">Right Side Push</a> </div> </div> <div class="content-body"> <p>The artilleryman agreed with me that the house was no place to stay in. He proposed, he said, to make his way Londonward, and thence rejoin his battery--No. 12, of the Horse Artillery. My plan was to return at once to Leatherhead; and so greatly had the strength of the Martians impressed me that I had determined to take my wife to Newhaven, and go with her out of the country forthwith. For I already perceived clearly that the country about London must inevitably be the scene of a disastrous struggle before such creatures as these could be destroyed.</p> <p>Between us and Leatherhead, however, lay the third cylinder, with its guarding giants. Had I been alone, I think I should have taken my chance and struck across country. But the artilleryman dissuaded me: "It's no kindness to the right sort of wife," he said, "to make her a widow"; and in the end I agreed to go with him, under cover of the woods, northward as far as Street Cobham before I parted with him. Thence I would make a big detour by Epsom to reach Leatherhead.</p> <p>I should have started at once, but my companion had been in active service and he knew better than that. He made me ransack the house for a flask, which he filled with whiskey; and we lined every available pocket with packets of biscuits and slices of meat. Then we crept out of the house, and ran as quickly as we could down the ill-made road by which I had come overnight. The houses seemed deserted. In the road lay a group of three charred bodies close together, struck dead by the Heat-Ray; and here and there were things that people had dropped--a clock, a slipper, a silver spoon, and the like poor valuables. At the corner turning up towards the post office a little cart, filled with boxes and furniture, and horseless, heeled over on a broken wheel. A cash box had been hastily smashed open and thrown under the debris.</p> </div><!--end content body--> </section><!--end content--> </div> <!--end container --> |
3. Adding style
Now comes the most important part of our build: adding the CSS styles.
First, we’ll hide the input checkbox and the .full-screen-close
label.
To make the full-screen label clickable, we’ll give it a width and height of 100% and to indicate that the area is clickable add a cursor: pointer
property.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/*===== SLIDE MENU ======*/ /*---------- HIDE SELECT CHECKBOX ----------*/ .toggle, .full-screen-close { display: none; } .full-screen-close { width: 100%; height: 100%; position: absolute; cursor: pointer; top:0; left:0; } |
Now it’s time to add the sliding functionality.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
.menu-container { background: #2c3e50; width: 40%; margin-left: -40%; float: left; height: 100%; position: absolute; z-index:99; } /*---------- TOGGLE OFF-CANVAS MENU ----------*/ .toggle:checked + .container > .menu-container { margin-left: 0; } .toggle:checked + .container > .content .full-screen-close { display: block; background: rgba(0,0,0,.5); } .menu-container, .content { transition: margin 0.5s ease-in-out; } |
First, we have to style the menu-container
. Set-up a background-color and a high z-index, so the menu will be visible. Now, give a width to the menu. You can give an absolute width, expressed in pixels or a relative one expressed in percentages. To hide the menu, give the margin-left a negative value. Note that the negative value must be equal to the one used in the width.
To show the menu, will use some advanced CSS selectors. The +
selector is used to select an element placed immediately after the chosen element. The > selector selects all the elements inside the parent element.
If the checkbox is checked we’ll select the container placed immediately after the input and the menu-container and apply a margin-left of 0, thus showing the menu. Instead of writing a ton of Java Script, we only had to write a few lines of CSS.
We can add a nice animation effect by adding a transition property to our .menu-container
and .content
divs.
Now we can start styling the toggle and close buttons.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
.menu { padding-top: 24px; } .toggle-btn, .close-btn { cursor: pointer; } .toggle-btn { font-size: 2.25rem; } .close-btn { float: right; font-size: 1.5rem; padding: 1.5rem; color: #ededed; } |
Styling the links in the menu is pretty easy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
.slide-menu i { margin-right: 1rem; font-size: 1.5rem; vertical-align: middle; } .slide-menu li a { color: #fff; padding: 1.5rem; font-size: 1.125rem; text-transform: uppercase; font-weight: 600; display: block; transition: background-color .5s ease-in-out; } .slide-menu li a:hover { background-color: #34495e; } |
As you can see, we added some paddings and margins to improve the design and also added background color to the hover state of our anchor tags.
At this point, we’re basically done. If you followed along, you should now have an off-canvas menu that slides from the left side of the screen. We can further improve the design by adding some media queries.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/*===== MEDIA QUERIES ======*/ @media (max-width: 460px) { .slide-menu li a { font-size: 0.875rem; padding-left: 12px; } .slide-menu li i { font-size: 16px; } } @media (max-width: 320px){ .slide-menu li i { display: none; } } |
At smaller screen sizes, I decreased the font size and paddings and removed the icons.
4. Different Off-Canvas effects
To push the text when the sidebar appears on the screen, we have to add a margin-left to the content of 40% or the value you defined the menu width:
1 2 3 4 |
.toggle:checked + .container > .content { margin-left: 40%; } |
If we want the slide menu to appear from the right side of the screen, we have to modify the CSS a little bit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
.menu-container { background: #2c3e50; width: 40%; margin-left: 100%; float: right; height: 100%; position: absolute; z-index:99; } .toggle:checked + .container > .menu-container { margin-left: 60%; } |
Instead of having a margin-left of -40% like in the previous example, we have to set the margin-left: 100%
. This will push the menu off-screen to the right side.
To show the menu, we can set the margin-left to 60%.
Pushing the content to the left when the menu appears is easy and we can apply the same technique we used before:
1 2 3 4 |
.toggle:checked + .container > .content { margin-right: 60%; } |
5. Additional styles
In the style.css I defined some general rules for the site: colors, fonts, margins and paddings. I also added some media queries to manage the layout for smaller screen sizes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
/*===== UTILITIES ======*/ *, *:after, *:before { -webkit-box-sizing: border-box; box-sizing: border-box; } .clearfix:before, .clearfix:after { content: " "; display: table; } .clearfix:after { clear: both; } /*===== GENERAL PAGE STYLES ======*/ html, body, .container, .menu-container{ width: 100%; /*full screen width*/ height: 100%; /*full screen height*/ overflow-x: hidden; /*no horizontal scroll bar*/ } a{ text-decoration: none; } ul{ list-style: none; margin: 0; padding: 0; } body { color: #808080; font-weight: 400; font-size: 1em; font-family: 'Raleway', Arial, sans-serif; } .content{ width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 1.5rem; line-height: 1.5; } h1{ text-align: center; font-weight: 500; text-transform: uppercase; font-size: 2.25rem; margin: 3rem 0; } /*===== AP META ======*/ .ap-meta{ text-align: center; font-size: 1.125rem; } .ap-meta a{ color: #2196F3; margin-right: 24px; } .ap-meta a:last-child{ margin-right: 0; } .ap-meta i{ margin-right: 6px; } /*===== SLIDE OPTIONS ======*/ .menu-options{ margin: 0 auto; margin-bottom: 48px; width: 30%; } .menu-options h3{ text-align: center; margin-top: 0; margin-bottom: 36px; } .menu-options a{ display: block; padding: 6px 12px; border: 1px solid #2196F3; border-radius: 5px; color: #2196F3; font-weight: 500; margin-bottom: 12px; transition: all .5s ease-in-out; } .menu-options a:hover{ background: #2980b9; color: #fff; } .left{ float: left; } .right{ float: right; } /*===== GENERAL MEDIA QUERIES ======*/ @media (max-width: 980px) { .menu-options{ width: 50%; } } @media (max-width: 605px) { .menu-options{ width: 80%; } } @media (max-width: 518px) { .ap-meta a span{ display: none; } } @media (max-width: 375px) { .ap-meta a span{ display: none; } header h1{ font-size: 1.5rem; font-weight: 600; } .menu-options{ width: 100%; } } @media (max-width: 330px) { .content{ padding: 0 1rem; } .menu{ margin-bottom: 1.5rem; } .ap-meta a span{ display: none; } header h1{ font-size: 1.125rem; font-weight: 600; } .menu-options{ width: 100%; } } |
Conclusion
As you can see, creating an Off – canvas navigation menu is really easy. I chose an elegant solution to toggle the navigation without using any Java Script.
I hope this lesson was useful and I encourage you to try this techniques in your next project!
Hello,
Your offcanvas is crazy!
I tried many scripts with jquery or pure css; on the net there are plenty of solutions;
but, yours in pure css is unique
because, when on mobile phone I scroll the slide bar, the background (behind) dont’ move!
with others solutions i tried in css, the background move and it is not professional
Have you the solution for “push slide bar”, yours is reveal
Thank you