Animate the overflow property

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.

Leave a Comment