BS5 Fly out nav bar design

I’m trying to create a fly out navbar designed like this This Site

Here is what I have so far
https://codepen.io/aaron4osu/pen/eYeGmBB

How do I make it slide out from the left rather than the right (while keeping the hamburger icon to the right)?

I also wanted to try to mimic the animation affect… I really like the double affect where the container slides out, then the nav items slide out.

<nav class="navbar  fixed-top navbar-dark bg-dark" aria-label="Main navigation">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">
      <!-- <img src="assets/img/Signal-Logo-white.png"> -->
      Logo Here

    </a>
    <button class="navbar-toggler p-0 border-0" type="button" id="navbarSideCollapse" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="navbar-collapse offcanvas-collapse" id="navbarsExampleDefault">
      <ul class="navbar-nav mx-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Company</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="dropdown01" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</a>
          <ul class="dropdown-menu list-inline" aria-labelledby="dropdown01">
            <li class="list-inline-item"><a class="dropdown-item " href="#">Service 1</a></li>
            <li class="list-inline-item"><a class="dropdown-item" href="#">Service 2</a></li>
            <li class="list-inline-item"><a class="dropdown-item" href="#">Service 3</a></li>
          </ul>
        </li>

      <li class="nav-item">
          <a class="nav-link" href="#">Services</a>
          <ul class="sub-menu list-inline" aria-labelledby="dropdown01">
            <li class="list-inline-item"><a class="" href="#">Service 1</a></li>
            <li class="list-inline-item"><a class="" href="#">Service 2</a></li>
            <li class="list-inline-item"><a class="" href="#">Service 3</a></li>
          </ul>
        </li>
         <li class="nav-item">
          <a class="nav-link" href="#">Contact</a>
        </li>
      </ul>
    </div>
  </div>
</nav>

css


html,
body {
  overflow-x: hidden; /* Prevent scroll on narrow devices */
}

body {
  padding-top: 56px;
}

.offcanvas-collapse {
    position: fixed;
    top: 56px; /* Height of navbar */
    bottom: 0;
    left: 100%;
    width: 70%;
    padding-right: 1rem;
    padding-left: 1rem;
    overflow-y: auto;
    visibility: hidden;
    background-color: #343a40;
    transition: transform .5s ease-in-out, visibility .5s ease-in-out;
  }
  .offcanvas-collapse.open {
    visibility: visible;
    transform: translateX(-100%);
  }

.nav-scroller {
  position: relative;
  z-index: 2;
  height: 2.75rem;
  overflow-y: hidden;
}

.nav-scroller .nav {
  display: flex;
  flex-wrap: nowrap;
  padding-bottom: 1rem;
  margin-top: -1px;
  overflow-x: auto;
  color: rgba(255, 255, 255, .75);
  text-align: center;
  white-space: nowrap;
  -webkit-overflow-scrolling: touch;
}

.nav-underline .nav-link {
  padding-top: .75rem;
  padding-bottom: .75rem;
  font-size: .875rem;
  color: #6c757d;
}

.nav-underline .nav-link:hover {
  color: #007bff;
}

.nav-underline .active {
  font-weight: 500;
  color: #343a40;
}

.bg-purple {
  background-color: #6f42c1;
}

.navbar-brand img{
  width: 150px;
}

.nav-item{
 
}

.nav-item{
    font-size: 52px;
    font-weight: bold;
    letter-spacing: 1px;
    line-height: 55px;
    opacity: 1;
    transition: transform .9s ease-in-out, visibility .9s ease-in-out;
  
    margin-top:20px;
}

.nav-item .sub-menu{
  font-size:20px;
  font-weight:300;
  color:#fff;
}
.nav-item .sub-menu a{
  color:#fff;
  text-decoration:none;
}

js

(function () {
  'use strict'

  document.querySelector('#navbarSideCollapse').addEventListener('click', function () {
    document.querySelector('.offcanvas-collapse').classList.toggle('open')
  })

})()

Any help would be greatly appreciated

You can change the direction by placing the nav off the left side instead of the right and then transition each list element with a different delay on each.

Here’s a start:

.offcanvas-collapse {
    position: fixed;
    top: 56px; /* Height of navbar */
    bottom: 0;
    left: 0;
    width: 70%;
    padding-right: 1rem;
    padding-left: 1rem;
    overflow-y: auto;
    visibility: hidden;
    background-color: #343a40;
   transform: translateX(-100%);
    transition: transform .5s ease-in-out, visibility .5s ease-in-out;
  }
  .offcanvas-collapse.open {
    visibility: visible;
    transform: translateX(0%);
  }
#navbarsExampleDefault > ul > li{
  transform:translateX(-100%);
  transition:transform 1s ease;
}

.offcanvas-collapse.open#navbarsExampleDefault > ul > li{
  transform:translateX(0%);
  transition-delay:0s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(1){
  transition-delay:.1s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(2){
  transition-delay:.2s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(3){
  transition-delay:.3s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(4){
  transition-delay:.4s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(5){
  transition-delay:.5s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(6){
  transition-delay:.6s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(7){
  transition-delay:.7s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(8){
  transition-delay:.8s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(9){
  transition-delay:.9s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(10){
  transition-delay:1s;
}
1 Like

that’s perfect… Thank you Paul!

1 Like

If you wanted the nav items to slide back out when you close you;d need to do the delays in reverse order. You’d also need to delay the main mav from closing first otherwise you won’t see it happen.

Roughly like this:

.offcanvas-collapse {
  position: fixed;
  top: 56px; /* Height of navbar */
  bottom: 0;
  left: 0;
  width: 70%;
  padding-right: 1rem;
  padding-left: 1rem;
  overflow-y: auto;
  visibility: hidden;
  background-color: #343a40;
  transform: translateX(-100%);
  transition: transform 0.5s ease-in-out, visibility 0.5s ease-in-out;
  transition-delay: 1s;
}
.offcanvas-collapse.open {
  visibility: visible;
  transform: translateX(0%);
  transition-delay: 0s;
}
#navbarsExampleDefault > ul > li {
  transform: translateX(-100%);
  transition: transform 1s ease;
}

.offcanvas-collapse.open#navbarsExampleDefault > ul > li {
  transform: translateX(0%);
  transition-delay: 0s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(1) {
  transition-delay: 0.1s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(2) {
  transition-delay: 0.2s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(3) {
  transition-delay: 0.3s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(4) {
  transition-delay: 0.4s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(5) {
  transition-delay: 0.5s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(6) {
  transition-delay: 0.6s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(7) {
  transition-delay: 0.7s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(8) {
  transition-delay: 0.8s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(9) {
  transition-delay: 0.9s;
}
.offcanvas-collapse.open#navbarsExampleDefault > ul > li:nth-child(10) {
  transition-delay: 1s;
}

.offcanvas-collapse.open#navbarsExampleDefault > ul > li {
  transform: translateX(0%);
}
#navbarsExampleDefault > ul > li:nth-child(1) {
  transition-delay: 0.9s;
}
#navbarsExampleDefault > ul > li:nth-child(2) {
  transition-delay: 0.8s;
}
#navbarsExampleDefault > ul > li:nth-child(3) {
  transition-delay: 0.7s;
}
#navbarsExampleDefault > ul > li:nth-child(4) {
  transition-delay: 0.6s;
}
#navbarsExampleDefault > ul > li:nth-child(5) {
  transition-delay: 0.5s;
}
#navbarsExampleDefault > ul > li:nth-child(6) {
  transition-delay: 0.4s;
}
#navbarsExampleDefault > ul > li:nth-child(7) {
  transition-delay: 0.3s;
}
#navbarsExampleDefault > ul > li:nth-child(8) {
  transition-delay: 0.2s;
}
#navbarsExampleDefault > ul > li:nth-child(9) {
  transition-delay: 0.1s;
}
#navbarsExampleDefault > ul > li:nth-child(10) {
  transition-delay: 0s;
}

Note that you only need enough rules to cover the amount of direct children links you have. I put in enough for 10 (li:nth-child(10)) but you should only really need to use the same amount as you have main links (ie. 5 in your demo).

1 Like

That works even better… Thanks again Paul!!!

How can I make it close if the user clicks anywhere outside of the expanded nav?

This is probably the wrong way to do it as bootstrap probably has a native way of handling this but you could add a backdrop div when the nav is opened and then check for a click on the backdrop element to close it.

e.g.

You should probably check the bootstrap documentation to see if there already is something like this baked in .

I’m coming back to this and trying to add a close button inside of navbar-collapse. So I would have the hamburger on the top right of the screen and the close button inside the flyout section (.navbar-collapse).

I’m not sure what I need to do on the JS side. I tried following the pattern of what I had and added a closebtn var and added that to the toggle function, but I’m getting an error (TypeError: null is not an object (evaluating ‘closebtn.classList’)) and it’s not working.

(function () {
  "use strict";
  const nav = document.querySelector("#navbarSideCollapse");
  const backdrop = document.querySelector(".backdrop");
  const body = document.querySelector("body");
  const hamburger = document.querySelector(".offcanvas-collapse");
  const closebtn = document.querySelector(".closebtn");

    nav.addEventListener("click", function (e) {
      e.preventDefault();
      hamburger.classList.toggle("open");
      body.classList.toggle("open");
      closebtn.classList.toggle("open");
    });

     backdrop.addEventListener("click", function (e) {
      if (body.classList.contains('open')) {
       hamburger.classList.toggle("open");
       body.classList.toggle("open");
       nav.classList.toggle("open");
       closebtn.classList.toggle("open");
      }
    });
  
  
  
})();

codepen
https://codepen.io/aaron4osu/pen/eYeGmBB

You have a typo where you look for .closebtn but it is actually .closeBtn (CamelCase B).

However you need a click event on the new button so do this instead.



(function () {
  "use strict";
  const nav = document.querySelector("#navbarSideCollapse");
  const backdrop = document.querySelector(".backdrop");
  const body = document.querySelector("body");
  const hamburger = document.querySelector(".offcanvas-collapse");
  const closebtn = document.querySelector(".closeBtn");
  closebtn.addEventListener("click", function (e) {
    e.preventDefault();
    hamburger.classList.toggle("open");
    body.classList.toggle("open");
  });

  nav.addEventListener("click", function (e) {
    e.preventDefault();
    hamburger.classList.toggle("open");
    body.classList.toggle("open");
  });

  backdrop.addEventListener("click", function (e) {
    if (body.classList.contains("open")) {
      hamburger.classList.remove("open");
      body.classList.remove("open");
      // nav.classList.remove("open");
    }
  });
})();

Also note that the new button is actually underneath the nav items so you can’t click it. You will need to raise the z-index as follows.

  #close{
    position: absolute;
    top: 50px;
    right: 10px;
    z-index:3;
  }

Edit: As all 3 functions are basically the same you could tidy up the code a little like this.

great thank you Paul!

1 Like