A simple vanilla JavaScript off-canvas navigation.

Download GitHub

Introduction, installation

Canvi is a simple off-canvas navigation with a few parameter to configure. You can init multiple instances, set responsive width, use your style our Canvi's style.

To install Canvi get the JS and the CSS file and insert into your project. You can also customize the Sass to save some byte.

// To the head
<link rel="stylesheet" href="dist/canvi.css">
// To the end of the body
<script src="dist/canvi.js"></script>

You can also use Canvi in webpack based projects using canvi-webpack.js with import.

import Canvi from 'dist/canvi-webpack';

Basic Usage

To use Canvi first, you have to implement the correct HTML structure which is mean the proper use of the .canvi-navbar and .canvi-content.

<!DOCTYPE html>
<html lang="en">
    <div class="canvi-navbar"></div>
    <div class="canvi-content"></div>

After this you need to call the Canvi constructor and viola you are done!

var canvi = new Canvi();
Open Left Navbar Open Right Navbar

Multiple Instance

To make multiple instances, you must specify the correct value for the content, navbar and openButton property. Note that the content can be the same on multiple initializations.

var canviLeft = new Canvi({
    content: '.js-canvi-content',
    navbar: '.js-canvi-navbar--left',
    openButton: '.js-canvi-open-button--left'

var canviRight = new Canvi({
    content: '.js-canvi-content',
    navbar: '.js-canvi-navbar--right',
    openButton: '.js-canvi-open-button--right'


Canvi using aria-hidden="true" when the navigation is hidden. If you want to be more accesible you can use the inert attribute - which is also used by Canvi - but for this you need to use this polyfill because it is quite a new feature. Just simply insert the script into your project.

If you like to know more about inert check out A11ycats #2 episode!



Type: string

Default: '.canvi-content'

This selector defines the content part of the markup. Mostly you need to modify this when you use multiple Canvi.


Type: boolean

Default: false

Canvi's debugger switch.


Type: string

Default: '.canvi-navbar'

Define the navbar part of the structure. This selector is part of the default markup. Mostly you need to modify it'value when you use multiple Canvi.


Type: string

Default: '0.3s'

You can specify here the opening/closing speed of the menu.


Type: string

Default: '.canvi-open-button'

Canvi open button selector.


Type: string

Default: 'left'

Specify the position of the navigation.


Type: boolean

Default: true

Set if you don't want the menu to push the content. In this case, it will lay over your page.


Type: string

Default: '300px'

Set the width of the navbar. You must give string with the correct unit so you can specify any value type like em, %, px.


Type: array

Default: []

With this option, you can modify the width of the navbar by breakpoints. This is a mobile first approach, and the very first width option will be width parameter's value.


Canvi comes with a few method so you can open and close it manually from your code. To use these methods, you must save the Canvi instance in a variable at the declaration like to following:

var canviRight = new Canvi({
    content: '.js-canvi-content',
    navbar: '.js-canvi-navbar--right',
    openButton: '.js-canvi-open-button--right',
    position: 'right',
    pushContent: true,
    width: '300px'


Open the Canvi instance.



Close the Canvi instance.



Toggle the Canvi instance.



Canvi came with custom events which you can use to customize, modify Canvi or your site's specific parts. To catch an event all you have to do is to define an event listener to the body element.

Each event gives back three additional Canvi elements named by navbar, openButton, content. You can access them through the event object like e.detail.navbar.


This event is triggered when Canvi initialization ready. To catch the initialization event, you have to watch the canvi.init event. Note that you must declare the following code before the Canvi constructor.

document.querySelector('body').addEventListener('canvi.init', function(e) {
    console.log('Catch Canvi init event...');


This event is triggered when you click on the menu open button. To catch the before-open event, you have to watch the canvi.before-open event.

document.querySelector('body').addEventListener('canvi.before-open', function(e) {
    console.log('Catch Canvi before-open event...');


This event is triggered after the menu opened. To catch the after-open event, you have to watch the canvi.after-open event.

document.querySelector('body').addEventListener('canvi.after-open', function(e) {
    console.log('Catch Canvi after-open event...');


This event is triggered before you close the menu. To catch the before-close event, you have to watch the canvi.before-close event.

document.querySelector('body').addEventListener('canvi.before-close', function(e) {
    console.log('Catch Canvi before-close event...');


This event is triggered after the menu closed. To catch the after-close event, you have to watch the canvi.after-close event.

document.querySelector('body').addEventListener('canvi.after-close', function(e) {
    console.log('Catch Canvi after-close event...');