Bootstrap is designed to cater for lots of scenarios by providing a handful of commonly-used web components. There are buttons, a responsive navigation bar, tabs, tooltips, carousels, and so forth. Still, even with all the toys Bootstrap gives us, it is still missing a very popular pattern: the off-canvas navigation.
This approach to navigation sets the menu off from the visible area (the canvas), giving more space to focus on the main content. Off-canvas navigation was first made popular in native mobile apps, after which it came to the responsive web (thanks in part to Luke Wroblewski's article). Commonly, it makes use of jQuery to toggle the state of the navigation.
Speaking of which, Bootstrap being so popular and the community support being so great, developers have created plugins or extensions to include components that are not available in the official Bootstrap. And that includes one for implementing an off-canvas navigation.
In this tutorial, I'll show you how to add an off-canvas navigation to Bootstrap with an extension called Jasny Bootstrap by Arnold Daniels. My two reasons for this option are:
- As the name implies, the extension is specifically built for Bootstrap. Hence, the code base therein falls in line with that from the Bootstrap. It follows Bootstrap conventions in terms of the naming and the methods for implementing components.
- Jasny Bootstrap ships with the off-canvas navigation plugin, which is flexibly configurable through a series of classes, HTML5 data attributes, and JavaScript initiation.
A Bit About Bower
During this tutorial I'll be walking you through a workflow which helps website maintainability using Bower. So, ensure that you have Bower installed already on your system. If you'd rather not use Bower, that's fine, but to get you started we have also published a handful of beginner tutorials on Bower.
- Meet Bower: A Package Manager For The Web
- Quick Tip: What to do When You Encounter a Bower File
- Essential JS Libraries for Web Design (on Tuts+ courses)
Well, let's get started.
1. Getting Started
Let's start off the project by creating the working directories where we will place the required bits and pieces.
1
2
3
4
5
6
7
8
|
working- dir |-- assets | |-- css | |-- img | `-- js `-- sources |-- js `-- less
|
We will use the assets folder to save the website assets like the images, stylesheets, JavaScript files, and the likes. The sources folder is where we will put the uncompiled source code of LESS and JavaScript. Afterwards, we will define the project specification — name, version, dependencies, and others — with Bower.
Run bower init
command in the working directory and fill out all the prompts.
You don't have to follow the inputs as shown above precisely; adjust the inputs as per your own requirements. Once it is completed, a new file name bower.json
should be present, containing the project specification that we have just filled in.
2. Installing the Project Dependencies
This project requires two frameworks; namely Bootstrap and Jasny Bootstrap. Before we install them, let's specify the directory name where Bower will have to install the packages. To do so, create a new file in the root level of the working directory named .bowerrc
and put the following lines in to name the folder.
1
2
3
|
{ "directory" : "components" }
|
Then, include these lines below in bower.json
, which will tell Bower that the project dependencies are Bootstrap and Jasny Bootstrap version 3.1.1 or newer.
1
2
3
4
|
"devDependencies" : { "bootstrap" : ">=3.1.1" , "jasny-bootstrap" : ">=3.1.1" }
|
In Terminal or Command Prompt, run bower install
command to grab the dependencies that swe have specified all at once.
As specified in .bowerrc
, the project dependencies should now be in a newly generated folder named components
.
3. Organizing the Stylesheets
With all the dependencies prepared, we can start working on the project! We will kick things off by organizing the stylesheets. There are four LESS stylesheets that we will have to create, namely:
variables.less
— as the name says, this stylesheet contains the variables used in Bootstrap. We'll make this copy in case we want to customize the variables, without affecting the original files (copy Bootstrap variables from this Gist).variables-jasny.less
— similarly, this stylesheet contains the variables used in the extension, Jasny Bootstrap (copy the variables here).app.less
— this stylesheet contains references to the Bootstrap and Jasny Bootstrap stylesheets we need to build the website (you can copy the content here).style.less
— we will write our very own styles in this stylesheet.
Create and put them together like so:
1
2
3
4
5
6
7
8
|
... `-- sources |-- js `-- less |-- app. less |-- style. less |-- variables-jasny. less `-- variables. less
|
The next thing is to compile these stylesheets. To do so, we will be using Koala with the following configuration:
- Make sure that the Auto Compile option is checked. So Koala will immediately compile LESS files into CSS whenever we make a change.
- Set the
app.less
as well as thestyle.less
output destination toassets/css/
directory. - Select the Source Map option to generate the
.map
for easier debugging of the stylesheet. If this is the first you've heard about Source Map, check out our tutorial on Tuts+ Code, Source Map 101.
Once the configuration are all set, compile the LESS to CSS.
Note: bear in mind that you're not obliged to use Koala if you prefer another way to compile your LESS files.
4. Building the Webpage
Create a new HTML file named index.html
. Aside from the basic HTML5 bare structure, the index.html
file will also contain the meta viewport tag, the meta description tag, the title, and the links to the stylesheets, like so:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<! DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1" > < meta name = "description" content = "A demonstration on adding off-canvas menu to Bootstrap with Jasny Bootstrap" > < title >Bootstrap Off-canvas Navigation</ title > < link href = "assets/css/app.css" rel = "stylesheet" > < link href = "assets/css/style.css" rel = "stylesheet" > </ head > < body > </ body > </ html >
|
The Off-canvas Navigation
Now let's add the off-canvas navigation. Jasny Bootstrap uses a similar approach to Bootstrap when it comes to the component markup. This is how we start off the off-canvas navigation structure:
1
2
|
< nav id = "offcanvas" class = "navmenu navmenu-inverse navmenu-fixed-right navmenu-site offcanvas" role = "navigation" > </ nav >
|
It comprises a handful of classes. Three classes namely navmenu
, navmenu-inverse
, navmenu-fixed-right
define the element as a navmenu. The navmenuis one of the Jasny Bootstrap components which sets the assigned element as a vertical navigation. The offcanvas
is the class that sets the element off the viewport. Additionally, we've also added a new class, navmenu-site
, which will allow us to customize the navigation with our very own styles.
The menu items within the off-canvas navigation can be laid out using the <ul>
element along with nav navmenu-nav
class, like so.
1
2
3
4
5
6
7
|
< nav id = "offcanvas" class = "navmenu navmenu-inverse navmenu-fixed-right navmenu-site offcanvas" role = "navigation" > < ul > < li >< a href = "#" >Home</ a ></ li > < li >< a href = "#" >Blog</ a ></ li > < li >< a href = "#" >Portfolio</ a ></ li > </ ul > </ nav >
|
You're quite welcome to include original Bootstrap components in conjunction with this markup, such as the Dropdowns and the Buttons.
The HTML markup for the navigation that we will add in this tutorial is pretty lengthy. So, for the sake of simplicity, the complete markup can be obtained through this Gist..
The Webpage Content
The following image shows our plan to lay out the webpage content:
As shown above, the website content will comprise a logo, a toggle button with the "Hamburger" icon to slide the navigation in and out, and a few lines of catchphrases with a big button — known as a call-to-action button
The HTML markup of the content is similarly lengthy to be pasted within this tutorial. Instead, feel free to copy the whole from this Gist.
5. The Styles
Many of the styles herein will be merely decorative, revolving around colors, sizes and positions. This decorative style will be achieved by customizing the Bootstrap predefined styles and writing our own styles. So, instead of walking through the steps that might already be obvious, I would like to point out a few key details that matter most.
First of all, before writing a single line, import the app.less
stylesheet into thestyle.less
. This will allow us to reuse the Variables and the Mixins within it.
1
|
@import (reference) 'app.less' ;
|
Secondly, we create a LESS variable to define the image path. We name the variable @path-img
.
1
|
@path-img: '../../assets/img/' ;
|
Anytime we will need to refer to an image within the stylesheet, we will include this variable. This example below shows how we use it to point to the logo.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
.masthead-brand { margin-top : 10px ; margin-bottom : 10px ; float : left ; text-align : left ; margin-top : -15px ; a { .text- hide (); display : inline- block ; background-image : url ( '@{path-img}logo.png' ); background-repeat : no-repeat ; background- size : 100% 100% ; width : 100px ; height : 33px ; } }
|
Vertical Centering
Lastly, we would like to center the content, the catchphrases and the button, vertically. CSS, at this point, has not yet given us a convenient way to align content vertically using only a single property declaration. Consequently, there are a number of ways to achieve it, and honestly none is better than any other.
In this case, we will align the content using the CSS Table display method. If you take a look at the webpage markup, you will see that we wrap the webpage content with two <div>
. Each <div>
is assigned with site-wrapper
and site-wrapper-inner
class, like so.
1
2
3
4
5
|
<div class= "site-wrapper" > <div class= "site-wrapper-inner" > ... </div> </div>
|
To align the content vertically, we set the display
property of site-wrapper
totable
, and make it span the entire viewport by specifying the width
and theheight
to 100%
. Then, we set the inner wrapper display
property to table-cell
. This now allows us to apply vertical-align
property to align the content vertically.
01
02
03
04
05
06
07
08
09
10
|
.site-wrapper { display : table; width : 100% ; height : 100% ; min-height : 100% ; } .site-wrapper-inner { display : table-cell ; vertical-align : middle ; }
|
Full details of the style rules can be obtained in this Gist.
6. Make the Webpage Come Alive
Once we've added the styles, the website should now have the look and feel, as the screenshot below:
However, the website is not yet fully functioning. Try clicking on the "Hamburger" icon; no off-canvas navigation sliding in. This functionality comes from the JavaScript library, hence we have to compile it and add it to the website.
There are four JavaScript libraries we need in order to use the off-canvas navigation, which are jQuery, transition.js, dropdown.js to enable the dropdown menu that we added in the navigation, and lastly the offcanvas.js. To compile them together, create a new JavaScript file in the source/js directory. In this case, we'll name it app.js.
1
2
3
4
5
|
... `-- sources |-- js | `-- app.js `-- less
|
Import the JavaScript libraries using the @koala-prepend
, like so.
1
2
3
|
// @koala-prepend "../../components/jquery/dist/jquery.js" // @koala-prepend "../../components/bootstrap/js/transition.js" // @koala-prepend "../../components/jasny-bootstrap/js/offcanvas.js"
|
Set the output to /assets/js directory, and hit the Compile button. Don't forget to link the compiled file in the web page.
1
|
< script src = "assets/js/app.min.js" ></ script >
|
Now, you should be able to slide the off-canvas navigation in and out.
Transition
Additionally, you may also add the following piece of JavaScript at the bottom of the page, which will enable the transition effect of the dropdown menu.
01
02
03
04
05
06
07
08
09
10
11
|
< script > (function() { var $offCanvas = $('#offcanvas'), $dropdown = $offCanvas.find('.dropdown'); $dropdown.on('show.bs.dropdown', function() { $(this).find('.dropdown-menu').slideDown(350); }).on('hide.bs.dropdown', function(){ $(this).find('.dropdown-menu').slideUp(350); }); })(); </ script >
|