Search code examples
htmlcsstwitter-bootstrapbootstrap-4hamburger-menu

Bootstrap 4 - How to prevent collapsing menu from collapsing all elements in the nav


I'm using a bootstrap 4 navbar and I want to prevent the logo and language switch from moving and collapsing with the menu when the hamburger menu is clicked. Here is all of my code. Also, here is the link to my codepen. Is this possible?

https://codepen.io/asizemore/pen/LYEgvOy?editors=1100

CSS

.logo {
  max-width: 130px;
}

.btn {
  font-family: 'Muli', sans-serif;
  font-weight: 900;
}

.btn {
  background: rgb(142, 63, 41);
  color: rgb(202, 171, 159);
}

.active {
  background: rgb(166, 73, 47);
  color: white;
}

HTML

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>

!--   NAV BAR -->
<nav class="navbar navbar-light fixed-top navbar-expand-lg bg-white">
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>

  <a class="navbar-brand mt-lg-0" href="#"><img src="https://via.placeholder.com/200x50" class="logo img-fluid"></a>

  <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
    <ul class="navbar-nav mx-auto mt-2 mt-lg-0">
      <li class="nav-item">
        <a class="nav-link" href="#">PURPOSE</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">FAMILY</a>
      </li>
       <li class="nav-item">
        <a class="nav-link" href="#">AGRICULTURE</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">ART</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">CONTACT</a>
      </li>

    </ul>

  </div>

<!--   LANGUAGE SWITCH -->

<div class="btn-group btn-toggle lang mr-1"> 
  <input type="button" name="lang" class="btn" value="ENG">

  <input type="button" name="lang" class="btn active" value="SPA">
</div>
</nav>

Solution

  • Place your language switch inside a .navbar-item, right after .navbar-brand and give it an order: 1 (which is bigger than the default of 0 - so it's going to be displayed as the last item of its parent) on the interval at which your .navbar is not collapsed. Since you're using .navbar-expand-lg, it's going to be @media (min-width: 992px) but if you used .navbar-expand-md it would have been min-width: 768px - or 576px for -sm. More about responsive breakpoints here.

    When the nav is collapsed, you don't need the order changed, so the language switcher is displayed before the menu (that's the reason we placed it after the logo in the first place). See it working:

    .logo {
      max-width: 130px;
    }
    
    .btn {
      font-family: 'Muli', sans-serif;
      font-weight: 900;
    }
    
    .btn {
      background: rgb(142, 63, 41);
      color: rgb(202, 171, 159);
    }
    
    .active {
      background: rgb(166, 73, 47);
      color: white;
    }
    
    @media(min-width: 992px) {
      .language-switch {
        order: 1;
      }
    }
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
    
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
    
    <nav class="navbar navbar-light fixed-top navbar-expand-lg bg-white">
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <a class="navbar-brand mt-lg-0" href="#"><img src="https://via.placeholder.com/200x50" class="logo img-fluid"></a>
      <div class="nav-item language-switch">
        <div class="btn-group btn-toggle lang mr-1">
          <input type="button" name="lang" class="btn" value="ENG">
          <input type="button" name="lang" class="btn active" value="SPA">
        </div>
      </div>
      <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
        <ul class="navbar-nav mx-auto mt-2 mt-lg-0">
          <li class="nav-item">
            <a class="nav-link" href="#">PURPOSE</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">FAMILY</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">AGRICULTURE</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">ART</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">CONTACT</a>
          </li>
        </ul>
      </div>
    </nav>

    Oh, and you need to come up with an solution on how to align the three (logo, language switch and toggler) when they don't actually fit in one line (devices narrower than ~450px). But that's a problem you basically asked for.

    Note: if you want the logo to be displayed first when navbar is collapsed, you could simply place it before the toggler and give the toggler either ml-auto mr-3 or ml-3 mr-auto to make it stick to either right or left side (having it centered would be sort of weird, IMHO). Example:

    .logo {
      max-width: 130px;
    }
    
    .btn {
      font-family: 'Muli', sans-serif;
      font-weight: 900;
    }
    
    .btn {
      background: rgb(142, 63, 41);
      color: rgb(202, 171, 159);
    }
    
    .active {
      background: rgb(166, 73, 47);
      color: white;
    }
    
    @media(min-width: 992px) {
      .language-switch {
        order: 1;
      }
    }
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
    
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
    
    !-- NAV BAR -->
    <nav class="navbar navbar-light fixed-top navbar-expand-lg bg-white">
      <a class="navbar-brand mt-lg-0" href="#"><img src="https://via.placeholder.com/200x50" class="logo img-fluid"></a>
      <button class="navbar-toggler mr-auto" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="nav-item language-switch">
        <div class="btn-group btn-toggle lang mr-1">
          <input type="button" name="lang" class="btn" value="ENG">
          <input type="button" name="lang" class="btn active" value="SPA">
        </div>
      </div>
      <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
        <ul class="navbar-nav mx-auto mt-2 mt-lg-0">
          <li class="nav-item">
            <a class="nav-link" href="#">PURPOSE</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">FAMILY</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">AGRICULTURE</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">ART</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">CONTACT</a>
          </li>
        </ul>
      </div>
    </nav>

    The same result could be achieved by using order: -1 on the logo (without switching its place in DOM with the toggler) on the proper responsive interval (i.e: below 991px in your case).