//- mixin for navigation items
mixin nav-item (navLinkText, navLinkIcon)
//navigation item
li.nav__item
//navigation link
a.nav__link(href="#" title= navLinkText)
i.nav__link-icon.material-icons= navLinkIcon
= navLinkText
//page block includes a navigation and a content block
.page
//navigation
nav.nav
//close button
.nav__close
//navigation list
ul.nav__list
+nav-item('Home', 'home')
+nav-item('About', 'equalizer')
+nav-item('Tour', 'business_center')
+nav-item('Settings', 'settings')
+nav-item('Plans', 'grade')
+nav-item('Log In', 'perm_identity')
//content part
.page__content
//open navigation button
.nav-open-btn
.nav-open-btn__bar
.nav-open-btn__bar
.nav-open-btn__bar
//content block
.content
h1 Off-Canvas #[span Navigation] Variations
.submenu
.submenu__item
a(href="https://github.com/eisenfox/off-canvas-navigation" title="Check on GitHub" target="_blanc")
i(class="material-icons") toc
| Check on GitHub
.submenu__item
a(href="http://100dayscode.co.uk/" title="Check Codepen Challenge" target="_blanc")
i(class="material-icons") toc
| Check Codepen Challenge
h2 Click the button to change the demo
//demo buttons
.demo-btns
button.demo-btn.js-active(type="button") Demo 1
button.demo-btn(type="button") Demo 2
button.demo-btn(type="button") Demo 3
button.demo-btn(type="button") Demo 4
button.demo-btn(type="button") Demo 5
View Compiled
//COMMON VARIABLES
$dark-theme-color: #1c1c1c;
$accent-theme-color: #4caf50;
$accent-theme-color1: #00BD9D;
$accent-theme-color2: #832161;
$accent-theme-color3: #FE9000;
$accent-theme-color4: #D72638;
$accent-theme-color5: #FC448D;
$light-theme-color: #fff;
//MIXINS
//transitions mixin
@mixin transition-mix($property: all, $duration: 0.2s, $timing: linear, $delay: 0s) {
transition-property: $property;
transition-duration: $duration;
transition-timing-function: $timing;
transition-delay: $delay;
}
//position absolute mixin
@mixin position-absolute ($top: null, $left: null, $right: null, $bottom: null) {
position: absolute;
top: $top;
left: $left;
right: $right;
bottom: $bottom;
}
/* common styles !!!YOU DON'T NEED THEM */
body {
font: {
family: 'Overpass', sans-serif;
size: 16px;
}
color: $dark-theme-color;
}
.content {
width: 550px;
padding-top: 50px;
margin: auto;
text-align: center;
}
h1 {
margin: 0;
font: {
weight: 400;
size: 35px;
}
span {
font: {
family: 'The Girl Next Door', cursive;
weight: 700;
}
color: $accent-theme-color;
}
}
.submenu {
display: flex;
justify-content: center;
margin: 10px auto 0;
}
.submenu__item {
display: flex;
align-items: center;
justify-content: center;
&:not(:last-child) {
margin-right: 30px;
}
a {
@include transition-mix;
display: inline-flex;
align-items: center;
font: {
size: 17px;
}
color: inherit;
text-decoration: none;
&:hover {
color: $accent-theme-color;
}
i {
color: $accent-theme-color;
margin-right: 5px;
}
}
}
h2 {
margin-top: 40px;
text-decoration: underline;
}
.demo-btns {
display: flex;
justify-content: space-between;
}
.demo-btn {
@include transition-mix;
padding: 8px 15px;
background-color: transparent;
outline: none;
border: 2px solid currentColor;
border-radius: 5px;
cursor: pointer;
&:nth-child(1) {
color: $accent-theme-color1;
}
&:nth-child(2) {
color: $accent-theme-color2;
}
&:nth-child(3) {
color: $accent-theme-color3;
}
&:nth-child(4) {
color: $accent-theme-color4;
}
&:nth-child(5) {
color: $accent-theme-color5;
}
&:hover,
&.js-active {
color: $light-theme-color;
&:nth-child(1) {
background-color: $accent-theme-color1;
border-color: $accent-theme-color1;
}
&:nth-child(2) {
background-color: $accent-theme-color2;
border-color: $accent-theme-color2;
}
&:nth-child(3) {
background-color: $accent-theme-color3;
border-color: $accent-theme-color3;
}
&:nth-child(4) {
background-color: $accent-theme-color4;
border-color: $accent-theme-color4;
}
&:nth-child(5) {
background-color: $accent-theme-color5;
border-color: $accent-theme-color5;
}
}
}
/* page's styles !!!YOU NEED THEM */
html,
body {
margin: 0;
padding: 0;
min-height: 100vh;
overflow-x: hidden;
}
.page,
.page__content {
position: relative;
}
.page {
min-height: 100vh;
perspective: 1500px;
background-color: rgba($dark-theme-color, .5);
}
.page__content {
min-height: 100vh;
background-color: $light-theme-color;
}
/* navigation styles */
$nav-width: 300px;
$nav-bg: $dark-theme-color;
$nav-padding: 30px;
$nav-list-offset-vert: 45px;
$nav-item-offset-vert: 20px;
$nav-icon-offset-horz: 10px;
.nav {
position: fixed;
top: 0;
bottom: 0;
width: $nav-width;
padding: $nav-padding;
box-sizing: border-box;
background-color: $nav-bg;
box-shadow: 4px 0 5px 0 rgba(0,0,0,0.14),
1px 0 10px 0 rgba(0,0,0,0.12),
2px 0 4px -1px rgba(0,0,0,0.3);
opacity: 0;
visibility: hidden;
z-index: 500;
}
/* nav list styles */
.nav__list {
position: relative;
padding: 0;
margin: $nav-list-offset-vert 0 0 0;
list-style-type: none;
}
/* nav item styles */
.nav__item {
&:not(:last-child) {
margin-bottom: $nav-item-offset-vert;
}
}
/* nav link styles */
.nav__link {
@include transition-mix;
display: inline-flex;
align-items: center;
color: $light-theme-color;
text-decoration: none;
&:hover {
color: $accent-theme-color;
}
}
/* nav link icon styles */
.nav__link-icon {
position: relative;
top: - 3px; /* !!!use only with material design icons */
margin-right: $nav-icon-offset-horz;
color: currentColor;
}
/* close icon styles */
.nav__close {
@include position-absolute($top: $nav-padding, $right: $nav-padding);
width: 40px;
height: 25px;
cursor: pointer;
/* close icon elements */
&:before,
&:after {
@include transition-mix;
display: block;
width: 4px;
height: 28px;
border-radius: 10px;
content: '';
transform-origin: center center;
background-color: $light-theme-color;
}
&:before {
@include position-absolute($top: 0, $left: 18px);
transform: rotate(-45deg);
}
&:after {
@include position-absolute($top: 0, $right: 18px);
transform: rotate(45deg);
}
/* hover effect */
&:hover {
&:before,
&:after {
background-color: $accent-theme-color;
}
}
}
/* nav open btn styles */
$nav-open-btn-vert-offset: 30px;
$nav-open-btn-horz-offset: 30px;
.nav-open-btn {
@include position-absolute($top: $nav-open-btn-vert-offset, $left: $nav-open-btn-horz-offset);
@include transition-mix();
width: 35px;
height: 25px;
overflow: hidden;
cursor: pointer;
//used to hide open btn when the nav is opened
&.js-hidden {
@include transition-mix($duration: 0s);
opacity: 0;
visibility: hidden;
}
}
.nav-open-btn__bar {
width: 100%;
height: 5px;
background-color: $dark-theme-color;
border-radius: 20px;
&:nth-child(1) {
@include position-absolute($top: 0, $left: 0);
}
&:nth-child(2) {
@include position-absolute($top: 10px, $left: 0);
}
&:nth-child(3) {
@include position-absolute($top: 20px, $left: 0);
}
}
/* Demo #1: styles */
$nav-list-offset-vert: 30px;
.nav--offcanvas-1 {
@include transition-mix();
left: (- $nav-width);
/* opened styles */
&.js-opened {
@include transition-mix($property: left);
left: 0;
opacity: 1;
visibility: visible;
}
}
.page__content--offcanvas-1 {
@include transition-mix();
left: 0;
/* opened styles */
&.js-opened {
@include transition-mix($duration: .3s);
left: $nav-width;
}
}
/* Demo #2: styles */
.nav--offcanvas-2 {
@include transition-mix();
left: (- $nav-width);
/* opened styles */
&.js-opened {
@include transition-mix($property: left);
left: 0;
opacity: 1;
visibility: visible;
}
}
.page__content--offcanvas-2 {
@include transition-mix();
transform: scale(1) translateX(0);
&.js-opened {
transform: scale(.8) translateX($nav-width / 2);
}
}
/* Demo #3: styles */
.nav--offcanvas-3 {
@include transition-mix();
left: (- $nav-width);
/* opened styles */
&.js-opened {
@include transition-mix($property: left);
left: 0;
opacity: 1;
visibility: visible;
}
}
.page__content--offcanvas-3 {
@include transition-mix();
transform: rotateY(0deg) translateX(0);
&.js-opened {
transform: translate3d(100px, 0, -600px) rotateY(- 20deg);
}
}
/* Demo #4: styles */
.nav--offcanvas-4 {
@include transition-mix($duration: 0s);
max-height: 80%;
transform: rotateY(-75deg) translateX(-50px);
transform-origin: left center;
/* opened styles */
&.js-opened {
max-height: 100%;
transition:
transform .22s linear 0s,
opacity .22s linear 0s,
visibility .22s linear 0s;
transform: rotateY(0) translateX(0);
transform-origin: left center;
opacity: 1;
visibility: visible;
}
}
.page__content--offcanvas-4 {
@include transition-mix();
left: 0;
/* opened styles */
&.js-opened {
left: $nav-width;
}
}
/* Demo #5: styles */
.nav--offcanvas-5 {
width: 50%;
&.js-opened {
@include transition-mix;
width: $nav-width;
opacity: 1;
visibility: visible;
}
}
.page__content--offcanvas-5 {
@include transition-mix();
left: 0;
/* opened styles */
&.js-opened {
left: $nav-width;
}
}
View Compiled
//CODE TO USE ON YOUR WEBSITE - !!! YOU NEED IT
//hide nav open btn when the nav is open, adding/removing open classes to nav and content
var navOpenBtn = document.querySelector('.nav-open-btn');
var navCloseBtn = document.querySelector('.nav__close');
var nav = document.querySelector('.nav');
var pageContent = document.querySelector('.page__content');
var navList = document.querySelector('.nav__list');
var page = document.querySelector('.page');
//open nav
navOpenBtn.addEventListener('click', function() {
navOpenBtn.classList.add('js-hidden');
nav.classList.add('js-opened');
pageContent.classList.add('js-opened');
});
//close nav
navCloseBtn.addEventListener('click', function() {
navOpenBtn.classList.remove('js-hidden');
nav.classList.remove('js-opened');
pageContent.classList.remove('js-opened');
});
//closing navigation if click outside it
page.addEventListener('click', function(e) {
var evTarget = e.target;
if((evTarget !== nav) && (nav.classList.contains('js-opened')) && (evTarget !== navOpenBtn) && (evTarget.parentNode !== navOpenBtn)) {
console.log(navOpenBtn.firstChild);
navOpenBtn.classList.remove('js-hidden');
nav.classList.remove('js-opened');
pageContent.classList.remove('js-opened');
}
});
//DEMO CODE - !!!YOU DON'T NEED IT
var demoBtns = document.querySelectorAll('.demo-btn');
//adding default demo classes
nav.classList.add('nav--offcanvas-1');
pageContent.classList.add('page__content--offcanvas-1');
//change demo on btn click
demoBtns.forEach(function(el, ind) {
el.addEventListener('click', function() {
//add active class to active btn
demoBtns.forEach(function(el) {
el.classList.remove('js-active');
});
this.classList.add('js-active');
//add proper classes for effects
var effClass = ind + 1;
nav.classList.remove('js-opened');
pageContent.classList.remove('js-opened');
navCloseBtn.classList.remove('js-opened');
navList.classList.remove('js-opened');
navOpenBtn.classList.remove('js-hidden');
nav.classList.remove(nav.classList[1]);
nav.classList.add('nav--offcanvas-' + effClass);
pageContent.classList.remove(pageContent.classList[1]);
pageContent.classList.add('page__content--offcanvas-' + effClass);
});
});
This Pen doesn't use any external JavaScript resources.