Jacob Stamm Jacob Stamm - 2 months ago 28
CSS Question

Smooth closing animation in mobile Bootstrap menu drop-down

I have drop-down lists in a Bootstrap 3 navbar-collapse that I want to animate smoothly upon opening and closing. Both the JavaScript and CSS animation solutions I found work great when viewing on a larger-width device. But when it's collapsed in mobile, closing a drop-down list looks awful. While it's collapsing, it goes back to looking like a standard drop-down list.

In this JSFiddle, try making the output window narrow so the menu collapses to mobile mode. Then, click the "hamburger" icon and open and close the "Some Stuff" drop-down. As you can see, it looks great when opening, but awful when closing. I've tried a lot of tinkering to no avail. Any idea on how this can be made smooth while in mobile mode?

NOTE: I prefer a CSS answer, but I'll use JavaScript if that's what it requires.

HTML



<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="#">Home</a></li>
<li>
<div class="navbar-nav-divider"></div>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" style="margin-bottom: 0;">
Some Stuff <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">Option 1</a></li>
<li><a href="#">Option 2</a></li>
<li><a href="#">Option 3</a></li>
</ul>
</li>
<li><a href="#">Contact</a></li>
</ul>
</div>
</div>
</nav>


CSS



.dropdown .dropdown-menu {
-webkit-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
-moz-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
-ms-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
-o-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;

max-height: 0;
display: block;
overflow: hidden;
opacity: 0;
visibility: hidden;
}

.dropdown.open .dropdown-menu {
-webkit-transition: max-height 0.3s, opacity 0.2s, visibility 0s;
-moz-transition: max-height 0.3s, opacity 0.2s, visibility 0s;
-ms-transition: max-height 0.3s, opacity 0.2s, visibility 0s;
-o-transition: max-height 0.3s, opacity 0.2s, visibility 0s;
transition: max-height 0.3s, opacity 0.2s, visibility 0s;

max-height: 120px;
opacity: 1;
visibility: visible;
}





EDIT:



I can get around this by skipping the close animation while in mobile mode, so it at least doesn't look horrible. However, I'm not considering it a solution, just a workaround. To implement it, I made the first of my two CSS blocks look like this instead:

.dropdown .dropdown-menu {
max-height: 0;
display: block;
overflow: hidden;
opacity: 0;
visibility: hidden;
}
@media (min-width: 768px) {
.dropdown .dropdown-menu {
-webkit-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
-moz-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
-ms-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
-o-transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
transition: max-height 0.3s, opacity 0.2s 0.1s, visibility 0s 0.3s;
}
}

Answer

Add this to your CSS so it keeps its styles even when it's closed.

@media (max-width: 767px) {
  .navbar-nav .dropdown-menu {
    position: static;
    float: none;
    width: auto;
    margin-top: 0;
    background-color: transparent;
    border: 0;
    -webkit-box-shadow: none;
    box-shadow: none;
  }
  .navbar-nav .dropdown-menu>li>a {
    padding: 5px 15px 5px 25px;
    color: #777;
  }
}

Here it is in action (Fiddle)