Reputation: 1828
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.
<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>
.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;
}
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;
}
}
Upvotes: 2
Views: 8917
Reputation: 1828
Use @AndrewBone's solution if you don't have access to the Bootstrap 3 LESS source code, as his answer is plug-and-play. My answer is slightly more performant, as it adds very little CSS, while making only a slight modification to the "root" styling.
Steps:
navbar.less
..open .dropdown-menu
and remove .open
from it so that the selector only says .dropdown-menu
. This will allow the CSS to apply to the mobile drop-down while it's opening and closing.This solves the styling/animation issue, but it leaves behind a gap due to the padding in the ul.dropdown-menu
element. We'll solve it by having zero padding on the ul
only when it's not opened (:not(.open) .dropdown-menu
) and animating that padding as well so it doesn't look jumpy.
Replace the custom CSS in the question with the following.
.navbar-nav .dropdown-menu {
-webkit-transition: max-height 0.4s, opacity 0.3s 0.1s, visibility 0s 0.3s, padding 0.4s ease;
-moz-transition: max-height 0.4s, opacity 0.3s 0.1s, visibility 0s 0.3s, padding 0.4s ease;
-ms-transition: max-height 0.4s, opacity 0.3s 0.1s, visibility 0s 0.3s, padding 0.4s ease;
-o-transition: max-height 0.4s, opacity 0.3s 0.1s, visibility 0s 0.3s, padding 0.4s ease;
transition: max-height 0.4s, opacity 0.3s 0.1s, visibility 0s 0.3s, padding 0.4s ease;
max-height: 0;
display: block;
overflow: hidden;
opacity: 0;
visibility: hidden;
}
.navbar-nav .dropdown.open .dropdown-menu {
-webkit-transition: max-height 0.4s, opacity 0.1s, visibility 0s, padding 0.2s ease;
-moz-transition: max-height 0.4s, opacity 0.1s, visibility 0s, padding 0.2s ease;
-ms-transition: max-height 0.4s, opacity 0.1s, visibility 0s, padding 0.2s ease;
-o-transition: max-height 0.4s, opacity 0.1s, visibility 0s, padding 0.2s ease;
transition: max-height 0.4s, opacity 0.1s, visibility 0s, padding 0.2s ease;
max-height: 120px;
opacity: 1;
visibility: visible;
}
.navbar-nav .dropdown:not(.open) .dropdown-menu {
padding: 0 !important;
}
And that's it! Now we have smooth CSS animations in both mobile and full-screen modes with minimal extra CSS that needs to be processed.
Upvotes: 0
Reputation: 7291
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)
Upvotes: 3