First off, just wanted to mention that I have read this thread:
CSS3 transition only when class is added, not when removed
and the solution there does not work for me. I have a nav that is hidden when the browser is within the small breakpoint, and is revealed when an element is clicked. Clicking the element adds a class via jQuery. Once open, there is a close button that when clicked removes the class. The class is adding and subtracting as expected, but for some reason the transition only works when the .open class is added, not when it's removed. Here's my code:
HTML:
<div class="menu-main-nav-container">
<ul id="menu-main-nav" class="menu">
<li id="menu-item-40" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-40"><a href="">What We Do</a></li>
<li id="menu-item-41" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-41"><a href="">Team</a></li>
<li id="menu-item-42" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-42"><a href="">Case Studies</a></li>
<li id="menu-item-102" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-102"><a href="">What Next?</a></li>
<li id="menu-item-104" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-104"><a href="#contact">Contact</a></li>
<li id="menu-item-122" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-122"><a href="#close">Close</a></li>
</ul>
</div>
CSS (Compass + Sass):
#menu-main-nav {
@include single-transition(opacity, 0.3s, ease-in-out);
opacity: 0;
position: absolute;
top: -27px;
left: 0px;
height: 0;
overflow: hidden;
z-index: 5000;
&.open {
opacity: 1;
height: auto;
}
}
CSS (Compiled):
#header #menu-main-nav {
transition: opacity 0.3s ease-in-out;
opacity: 0;
position: absolute;
top: -27px;
left: 0px;
height: 0;
overflow: hidden;
z-index: 5000;
}
#header #menu-main-nav.open {
opacity: 1;
height: auto;
}
jQuery:
$('body').on('click', '.menu-main-nav-container', function(e) {
if(!$mobileNav.hasClass('open')) {
$mobileNav.addClass('open');
}
}).on('click', '.nav-close', function(e) {
if($mobileNav.hasClass('open')) {
$mobileNav.removeClass('open');
}
})
});
I'm pretty stumped here. Keep in mind that I am using Compass and that the initial transition is working as expected.
First off, just wanted to mention that I have read this thread:
CSS3 transition only when class is added, not when removed
and the solution there does not work for me. I have a nav that is hidden when the browser is within the small breakpoint, and is revealed when an element is clicked. Clicking the element adds a class via jQuery. Once open, there is a close button that when clicked removes the class. The class is adding and subtracting as expected, but for some reason the transition only works when the .open class is added, not when it's removed. Here's my code:
HTML:
<div class="menu-main-nav-container">
<ul id="menu-main-nav" class="menu">
<li id="menu-item-40" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-40"><a href="http://blackandwright./what-we-do">What We Do</a></li>
<li id="menu-item-41" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-41"><a href="http://blackandwright./team">Team</a></li>
<li id="menu-item-42" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-42"><a href="http://blackandwright./case-studies">Case Studies</a></li>
<li id="menu-item-102" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-102"><a href="http://blackandwright./what-next">What Next?</a></li>
<li id="menu-item-104" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-104"><a href="#contact">Contact</a></li>
<li id="menu-item-122" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-122"><a href="#close">Close</a></li>
</ul>
</div>
CSS (Compass + Sass):
#menu-main-nav {
@include single-transition(opacity, 0.3s, ease-in-out);
opacity: 0;
position: absolute;
top: -27px;
left: 0px;
height: 0;
overflow: hidden;
z-index: 5000;
&.open {
opacity: 1;
height: auto;
}
}
CSS (Compiled):
#header #menu-main-nav {
transition: opacity 0.3s ease-in-out;
opacity: 0;
position: absolute;
top: -27px;
left: 0px;
height: 0;
overflow: hidden;
z-index: 5000;
}
#header #menu-main-nav.open {
opacity: 1;
height: auto;
}
jQuery:
$('body').on('click', '.menu-main-nav-container', function(e) {
if(!$mobileNav.hasClass('open')) {
$mobileNav.addClass('open');
}
}).on('click', '.nav-close', function(e) {
if($mobileNav.hasClass('open')) {
$mobileNav.removeClass('open');
}
})
});
I'm pretty stumped here. Keep in mind that I am using Compass and that the initial transition is working as expected.
Share Improve this question edited May 23, 2017 at 12:16 CommunityBot 11 silver badge asked Jul 3, 2015 at 23:45 HendecaHendeca 9432 gold badges15 silver badges32 bronze badges 6- Can you add your piled CSS and/or create an MCVE? – Alexander O'Mara Commented Jul 4, 2015 at 0:18
-
It's because the
height
goes from0
toauto
instantly. This is ok when you add class.open
, because the animation happens after theheight
expands toauto
. But you don't see the animation when the.open
class is removed, because theheight
goes to0
first and then the animation happens. – Suvi Vignarajah Commented Jul 4, 2015 at 0:27 - @SuviVignarajah I tried including a transition (still the same easing function and duration) to the height and changing height: auto to height: 300px (because if I'm not mistaken css transitions will not work with height: auto) and the problem persists. When the .open class is added, the menu fades in and drops down (increases in height). However when I click a second time, it just disappears suddenly as before. – Hendeca Commented Jul 4, 2015 at 8:55
- @AlexanderO'Mara Just added the relevant lines of the piled CSS file – Hendeca Commented Jul 4, 2015 at 8:59
-
@SuviVignarajah is right about why it happens. Here's an example of making it work with fixed height. jsfiddle/c10n8juh There are different ways you could solve this. Why are you changing the
height
andopacity
? – Alexander O'Mara Commented Jul 4, 2015 at 15:50
2 Answers
Reset to default 4As mentioned in the ments, the issue is that height: 0
immediately hides the element when the class is removed. The opacity still transitions, but you don't see it.
Unfortunately, since height: auto
is not a transitionable value, adding a height to the transition is not going to help. You could do it with a fixed height, if you set a delay when the open class is not present, but remove the delay when it is added.
var $menu = $('#menu-main-nav');
setInterval(function() {
$menu.toggleClass('open');
}, 2000);
#menu-main-nav {
background: grey;
overflow: hidden;
height: 0;
opacity: 0;
transition: opacity 1s, height 0s 1s;
}
#menu-main-nav.open {
height: 300px;
opacity: 1;
transition: opacity 1s, height 0s;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="menu-main-nav-container">
<ul id="menu-main-nav" class="menu">
<li><a href="#">What We Do</a></li>
<li><a href="#">Team</a></li>
<li><a href="#">Case Studies</a></li>
<li><a href="#">What Next?</a></li>
<li><a href="#contact">Contact</a></li>
<li><a href="#close">Close</a></li>
</ul>
</div>
As an alternative to fixed height
, if you do not rely on the layout of the element when expanded, you could use visibility
which is transitionable (well, you can delay it by a transition anyway), using the same technique above.
var $menu = $('#menu-main-nav');
setInterval(function() {
$menu.toggleClass('open');
}, 2000);
#menu-main-nav {
background: grey;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
#menu-main-nav.open {
opacity: 1;
visibility: visible;
transition: opacity 1s, visibility 0s;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="menu-main-nav-container">
<ul id="menu-main-nav" class="menu">
<li><a href="#">What We Do</a></li>
<li><a href="#">Team</a></li>
<li><a href="#">Case Studies</a></li>
<li><a href="#">What Next?</a></li>
<li><a href="#contact">Contact</a></li>
<li><a href="#close">Close</a></li>
</ul>
</div>
However, this means that the element will always the same height. If you do need the element to have a variable height, you could use JavaScript to calculate the target height, and set it to a fixed height for the duration of the animation.
try this, you just forgot the "" in your body element, and put the elements inside () Like this:
$(document).ready(function(){
$("body").on('click', '.menu-main-nav-container', function(e) {
if(!$("mobileNav").hasClass('open')) {
$("mobileNav").addClass('open');
}
}).on('click', '.nav-close', function(e) {
if($("mobileNav").hasClass('open')) {
$("mobileNav").removeClass('open');
}
})
});