【问题标题】:Animate the overflow property动画溢出属性
【发布时间】:2015-09-13 02:13:48
【问题描述】:

我需要为高度设置动画,并为第一个关键帧设置overflow: hidden,为最后一个关键帧设置overflow: visible(并保留它)。

我正在尝试这个,但最后,overflow 仍然是hidden

我该如何解决这个问题?

这 2 个包含仅仅是 SCSS polifill mixins。

@include keyframes(open) {
  0% {
    height: 0;
    overflow: hidden;
  }
  100% {
    height: $main_menu_height;
    overflow: visible;
  }
}


#main-menu-box {
    overflow: hidden;
    height: 0;

    &.opened{
       @include animation('open 200ms ease-out 0s 1 normal forwards');
    }
}

【问题讨论】:

    标签: css overflow css-animations keyframe


    【解决方案1】:

    在大多数现代浏览器中,clip-path(在 Safari 中以-webkit- 为前缀)是一个动画属性,有时可以用作overflow 的替代品。

    在原始示例中,使用clip-path 模拟在最后一帧翻转overflow 的最接近方法如下所示:

    @include keyframes(open) {
      0% {
        height: 0;
        clip-path: inset(0);
      }
      99.99999% {
        clip-path: inset(0);
      }
      100% {
        height: $main_menu_height;
        clip-path: inset(-100vh -100vw);
      }
    }
    
    #main-menu-box {
      clip-path: inset(0);
      height: 0;
    
      &.opened {
         @include animation('open 200ms ease-out 0s 1 normal forwards');
      }
    }
    

    由于这个动画是一个简单的线性动画,它甚至可以用常规的 CSS 过渡来代替:

    #main-menu-box {
      clip-path: inset(0);
      height: 0;
      transition: clip-path 0s ease-out, height 200ms ease-out;
    
      &.opened {
        height: $main_menu_height;
        clip-path: inset(-100vh -100vw);
        transition-delay: 200ms, 0s;
      }
    }
    

    但是,clip-pathoverflow 之间存在两个显着差异,这使得它不适用于所有情况。

    首先,与具有overflow: visible 的元素不同,具有任何clip-path 的元素具有stacking context,因此溢出内容的呈现方式将有所不同——尽管在具有溢出内容的菜单的情况下,您可能还是想要这个!

    其次,不像overflow 只剪辑子元素,clip-path 剪辑整个 元素。这意味着如果您有边框、框阴影等,它们也会被剪裁。根据容器的设计,有时可以通过将剪辑应用到子包装元素来解决此问题。

    【讨论】:

      【解决方案2】:

      解决方案是使用 AnimationEvent 侦听器。这是我的原始实现:

      CSS

      • 2 个动画(打开、关闭)

      • 2 节课(开课、闭课)

      • 2 种状态(溢出隐藏/可见)

      打开和关闭总是在动画开始时切换,而隐藏/可见状态在动画结束时会有所不同。

      注意:您会看到一个#main-menu 元素:它是一个在 y 轴上带有过渡平移的 UL,因为整个东西是一个菜单向下/向上滑动效果。

          @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

      • 汉堡是一个简单的开/关按钮

      • 现在我不得不同时使用 jquery 和 vanilla 选择器..

      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');
        }
      });
      

      这对我有用。

      【讨论】:

      • 你能包括一个sn-p,还是一个小提琴?
      • 另外,这是一篇旧帖子,不确定它是否仍然是真正最好/一流的解决方案。也许吧,但我应该调查一下。
      • 我只是想看看它的实际效果! :)
      【解决方案3】:

      overflow 属性不能使用 CSS 进行动画处理。在此处查看 W3 规范:overflow properties

      动画:无

      您还可以在 MDN 上查看动画属性列表:Animated properties


      解决方法:

      如果需要改变overflow属性,可以使用JS。这是 jQuery 库的示例。

      溢出属性随类切换而变化。单击 div 时会触发它:

      $('#w').click(function() {
        $(this).toggleClass('open');
      });
      #w {
        width: 100px;
        height: 100px;
        border: 1px solid red;
        overflow: hidden;
      }
      #w.open {
        overflow: visible;
      }
      #w div {
        height: 200px;
        width: 50px;
        background: gold;
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <div id="w">
        <div></div>
      </div>

      【讨论】:

        猜你喜欢
        • 2017-06-12
        • 1970-01-01
        • 2013-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多