Mobile Side Nav Menu Theme with Login/Logout Support that (CSS and Javascript)

This post shows how to change your page menu theme to permanently be the Mobile Menu Side Nav. This side nav is compatible with Mobile/Desktop, supports dropdown menus, and dynamically shows Login or Logout based on user's login status. This works on all pages including those which require login and those which don't. Here are some screenshots in reference to what we are about to create:

How it Looks:

Menu Closed:

![](upload://r6mrDnBsWMGR8DwfNJEcT4xrnaO.png)

Menu Open (User is Logged In)

![](upload://gNx2yBre3cfdrZPeIi6OgVoxiOB.png)

Menu Open (User is Logged Out)

![](upload://pyCo2fCAZ4b1Lrcv1l8x4lzr9Co.png)

CSS

Note: You can copy/paste this without any edits. Please review the Optional section to customize your theme colors. I included instructions where applicable so you can know what each setting changes.

/************************************/
/* Use a Mobile Dropdown Menu Only */
/**********************************/
/* Hides Desktop Menu */
ul#app-menu-list {display: none !important;}

/* Adds Mobile Modal Background to Desktop Mode */
#mobile-modal-bg { display: block !important; }

/* Always Display Mobile Controls */
.kn-mobile-controls {display: block !important; }

/* Allows Mobile Menu to Function on Desktop */
#kn-mobile-menu.is-visible {left: inherit !important; width: 70vw !important; }

/* Fixes Margin Change From Mobile to Desktop */
.kn-dropdown-menu ul li {
margin: unset !important;
}

/* Shows Drop-down Menu Items */
.kn-dropdown-menu ul {
display: block !important;
position: inherit !important;
box-shadow: unset !important;
}

/* Removes Carrot from Dropdown */
span.kn-dropdown-icon.fa.fa-caret-down {display: none !important;}

/* Drop Down Header Cannot Be Selected */
li.kn-dropdown-menu a:first-child {pointer-events: none;}

/* If User Clicks a Dropdown Header, Don't Set a Background Color for That Header */
#kn-mobile-menu li.kn-dropdown-menu.is-active {background-color: unset !important;}

/* Drop Down List Items Can Be Selected */
li.kn-dropdown-menu ul.kn-dropdown-menu-list a {pointer-events: all;}

/* Adds Transition When Opening Side Nav */
#kn-mobile-menu {transition: all 0.4s ease-out; width: 0%;}

/* Adds Transition to Each Child of Side Nav. Whitespace Fix for Clean Transition */
#kn-mobile-menu * {transition: all 0.2s linear; white-space: nowrap;}

/* Login Text Matches Logout */
a.kn-log-in, a.kn-psuedo-log-out {color: rgba(0,0,0,.6);}

/*************/
/* OPTIONAL */
/***********/
/* Set Custom Background Color for Active Page in Mobile Menu */
#app-menu-list-mobile li.is-active {background-color: #89b9e2;}

/* List Items Are Black, Change to Inherit if You Want Your Theme Colors */
.kn-dropdown-menu ul a {color: rgba(0,0,0,.8) !important;}

/* Set Custom Text Color for Active Page in Mobile Menu */
#kn-mobile-menu .is-active a {color: #000 !important;}

Javascript

Note: You will need to update the Scene ID for "Log Out Page Settings" and you will need to follow the instructions listed in that code section for the Log Out function to work. Another required update is to change the URL for the constant "homepage" to your site's homepage in two places .

/*********************/
/* Mobile Login/Out */
/*******************/
/*/ Launches Code on Scene Render Event /*/
$(document).on('knack-scene-render.any', function(event, scene) {

/*/ Logout Redirects to Welcome Page /*/
const homepage = "https://company.knack.com/site#welcome/"; // Change URL to Desired Page (ex: Site's Homepage)
$('.kn-log-out').on("click", function(){
let KnackScenes = $(".kn-scenes.kn-section");
KnackScenes.hide()
setTimeout(function () {
window.location = homepage;
KnackScenes.show(100);
}, 1000);
});

/*/ Creates Logout and Login Buttons When On Non-login Required Pages /*/
let mobile_user_info = $(".kn-mobile-user-info");
if (Knack.session.user) {
if (mobile_user_info.length > 0) {
} else {
let html = MobileAccount.logout();
let app_menu = $("#app-menu-list-mobile");
$(html).insertBefore(app_menu);
}
} else {
let html = MobileAccount.login();
let app_menu = $("#app-menu-list-mobile");
$(html).insertBefore(app_menu);
}
});

/*/ Object Used to Store and Retrieve HTML Config for Mobile Login/Logout /*/
var MobileAccount = {
logout: function() {
var html = '<section class="kn-mobile-account-container">' +
'<div class="kn-mobile-user-info">' +
'<!-- <div class="kn-mobile-account-photo"></div> -->' +
'<div class="kn-mobile-account-name">' +
Knack.getUserAttributes().name +
'</div>' +
'</div>' +
'<div class="kn-mobile-account-actions">' +
'<ul id="app-menu-user-pages-list-mobile" class="kn-menu-list">' +
'<li>' +
'<a href="#log-out" class="kn-psuedo-log-out">' +
'Log Out' +
'</a>' +
'</li>' +
'</ul>' +
'</div>' +
'</section>';
return html;
},
login: function() {
let Header = 'Welcome'
var html = '<section class="kn-mobile-account-container">' +
'<div class="kn-mobile-user-info">' +
'<!-- <div class="kn-mobile-account-photo"></div> -->' +
'<div class="kn-mobile-account-name">' +
Header +
'</div>' +
'</div>' +
'<div class="kn-mobile-account-actions">' +
'<ul id="app-menu-user-pages-list-mobile" class="kn-menu-list">' +
'<li>' +
'<a href="#login-page" class="kn-log-in">' +
'Log In' +
'</a>' +
'</li>' +
'</ul>' +
'</div>' +
'</section>';
return html;
}
}

/*********************************************************************************************/
/* Log Out Page Settings */
/* This is a Custom Page You'll Need to Create That Has Literally Nothing On It */
/* This Page DOES Require Login and All Users MUST Have Access to It */
/* I just use this page to store a log-out element made from script */
/* This logout element is only used on pages which don't require login */
/* I used this method due to bugs logging out from the mobile menu, this resolved that */
/**************************************************************************************/
$(document).on('knack-scene-render.scene_96', function (event, scene) { // Use Scene ID for Your Log Out Page
let KnackScenes = $(".kn-scenes.kn-section");
function redirect (destination = "https://company.knack.com/sitepage/") { // Change URL to Homepage or Other Destination
setTimeout(function(){
window.location = destination;
KnackScenes.show(100);
}, 1000);
}
function logoutUser(button = document.createElement("a")) {
button.className = "kn-log-out";
button.innerHTML = "Click to Log Out";
document.getElementById("kn-" + scene.key).appendChild(button);

button.addEventListener("click", function() {
KnackScenes.hide();
redirect();
});
button.click();
}
if (Knack.session.user) {logoutUser()} else {redirect()}
});

Notes for Other Developers:

CSS Approach

Rather than reinventing the wheel, my approach here was to apply all of Knack's pre-existing mobile side nav elements to all screen-widths in CSS. I inspected the mobile version's DOM and overwrote all "min-screen-width" pieces using the "!important" command. Also noticed a couple of bugs in Knack's mobile side nav which I fixed:

  1. Dropdown menus were buggy and non functional in multiple different ways. Most of the CSS is dedicated to these various fixes.
  2. No Transition When Opening Nav (added a linear slide animation)

Javascript Approach

This section only exists because the Login/Logout Button needs to be on every page. It doesn't make sense to have a website which only lets you login from certain pages.

  1. Added a redirect upon Logout which takes the user back to the homepage so we can control the login experience. Rather than having multiple login pages to manage, I opted for one login page that everyone shares.
  2. Copied the html markup from the user account section and reinserted it into the mobile side nav when on a non-login page so that every page has the "login" or "logout" button.
  3. The object is simply used to store the html markup for the "login" and "pseudo-log-out" buttons (more on pseudo-log-out in Step 4). You could embed that into the scene-render event if you want so it wouldn't be a global scope variable. I didn't so I could section out the code better here for readability.
  4. Log Out Page: Necessary evil. I noticed during testing that clicking the "logout" button from a non-login page using Step 2's html code would not log the user out. So, if we are a non-login page, I added a "psuedo-log-out" button into the html markup which redirects the user to this logout page that will log the user out correctly.
  5. Did you notice "<!-- <div class="kn-mobile-account-photo"></div> -->" in the html? Knack has a profile photo section built-in that they don't use. If you want to use it, you can.
2 Likes

397074362332,

Should be possible. That's a great idea for when you have a TON of pages in the side bar. I'll play around with it a little and see if I can squeeze that in there. If I find a solution then I'll add a follow-up comment to let you know and update the main code here as well.

Thank you Robert, works great!

Will it be possible to add code to collapse dropdown menu items?

Thank you

Just fantastic Robert. Thank you. 

Awesome as always Robert - thanks for the share.