The solution is to use AnimationEvent listeners. Here’s my raw implementation:
CSS
• 2 animations (open, close)
• 2 classes (opened, closed)
• 2 states (overflow hidden/visible)
opened and closed are always toggled at animationstart, while hidden/visible states are differently worked out on animationend.
Note: you’ll see a #main-menu element: it’s an UL with transitioned translations on y-axis, because the whole thing is a menu slide-down/up effect.
@include keyframes(open) { 0% { height:0; } 100% { height:$main_menu_height; } } @include keyframes(close) { 0% { height:$main_menu_height; } 100% { height:0; } } #main-menu-box{ overflow-y:hidden; height:0; // js &.closed{ @include animation('close 200ms ease-out 0s'); } &.opened{ @include animation('open 200ms ease-out 0s 1'); //#main-menu{ // @include translate(0, 0); //} } &.overflow-hidden{ overflow-y:hidden; } &.overflow-visible{ overflow-y:visible; } }
JS
• hamburger is a simple on/off button
• for now I had to use both jquery and vanilla selectors..
function poly_event_listener(element, type, callback) { var pfx = ['webkit', 'moz', 'MS', 'o', '']; for(var i=0; i<pfx.length; i++) { if (pfx[i] === '') type = type.toLowerCase(); element.addEventListener(pfx[i]+type, callback, false); } } var hamburger = $('header .hamburger'); var main_menu_box = $('#main-menu-box'); var main_menu_box_std = document.querySelector('#main-menu-box'); var init_menu = true; hamburger.click(function(){ if(init_menu){ main_menu_box.addClass('opened'); init_menu = false; return; } main_menu_box.toggleClass('opened closed'); }); poly_event_listener(main_menu_box_std,'AnimationStart',function(e){ main_menu_box.addClass('overflow-hidden'); main_menu_box.removeClass('overflow-visible'); }); poly_event_listener(main_menu_box_std,'AnimationEnd',function(e){ // in all the other cases I want hidden:true, visible:false // if class == closed, since animationend comes after animationstart, the state will already be hidden:true, visible:false // so non need to check for 'closed' here if(main_menu_box.hasClass('opened')){ main_menu_box.addClass('overflow-visible'); main_menu_box.removeClass('overflow-hidden'); } });
This works for me.