CSS Transition from display none to display block and vice versa

后端 未结 2 825
悲哀的现实
悲哀的现实 2021-01-05 04:08

I know this question has probably been asked million times here in SO, but Ive tried most of the solution, I just dont know why it dont work for me.

So I have a drop

2条回答
  •  臣服心动
    2021-01-05 04:30

    display your element at all times and only transition any animatable property. In your case, opacity looks like a good candidate, though playing with transform might also give you the desired result. Simple example:

    any {
      transform: scale(0);
      transition: transform .4s cubic-bezier(.5,0,.3,1);
    }
    any.animated {
      transform: scale(1);
    }
    

    In effect, opacity and transform should be the only two properties you should animate, as they don't require DOM repaint on anything other than the animated element, thus not hitting browser performance, even when you're animating a considerable amount of elements simultaneously.

    Please note that, even if not painted, your elements are, in effect, in the place where they would be when not transformed at all. So you might want to give them pointer-events:none when they are in the "invisible" state and pointer-events:all when they are in "visible" state, so they don't catch any pointer events while not visible.


    Considering your example, I've given you two animation examples (with keyframes and without). Remember you need to prefix your code. For full browser compatibility, use > 0% in settings (the small box at the bottom).

    setTimeout(function(){
      var dm = document.querySelector('.dropdown-menu');
      dm.classList.remove('hide-menu');
    }, 300);
    /* simple animation example, on parent. No keyframes. */
    .dropdown-menu.hide-menu {
      opacity: 0;
    }
    .dropdown-menu {
      opacity: 1;
      transition: opacity .2s cubic-bezier(.4,0,.2,1);
      position: relative;
      animation: delay-overflow .3s;
      animation-fill-mode: forwards;
      animation-iteration-count: 1;
    }
    .dropdown-menu:hover {
      animation: none;
      cursor: pointer;
    }
    
    /* animation example with keyframes, on child */
    
    .dropdown-menu ul {
      position: absolute;
      margin-top: 0;
      padding-top: 1rem;
      top: 100%;
      opacity: 0;
      transform: translateY(-10%);
      animation: slide-up .3s;
      animation-fill-mode: forwards;
      animation-iteration-count: 1;
    }
    
    .drowdown-menu.hide-menu ul {
      animation-duration: 0s;
    }
    .dropdown-menu:hover ul {
      animation: slide-down .3s;
      animation-fill-mode: forwards;
    }
    
    
    @keyframes slide-down {
      from {
        opacity: 0;
        transform: translateY(-10%);
      }
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }
    
    @keyframes slide-up {
      from {
        opacity: 1;
        transform: translateY(0);
      }
      to {
        opacity: 0;
        transform: translateY(-10%);
      }
    }
    @keyframes delay-overflow {
      0% {
        overflow: visible;
      }
      99% {
        overflow: visible;
      }
      100% {
        overflow: hidden;
      }
    }

    Note: A very handy trick with animation property is that it allows you to delay applying any property, even non-animatable ones from applying for the desired amount of time. I'm using this trick to delay overflow:hidden applying on the parent (and overflow is not animatable) so the animation of the child - which happens outside the bounds of the parent - is visible until the end. After it finishes, the overflow:hidden applies and it no longer catches mouse events outside the menu opener.

提交回复
热议问题