动画溢出 属性

Animate the overflow property

我需要设置高度动画,并为第一个关键帧设置 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 对溢出 属性 进行动画处理。请在此处查看 W3 规范:overflow properties

Animatable: no

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


解决方法:

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

溢出 属性 随 class 切换而变化。单击 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>

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

CSS

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

• 2 类(打开,关闭)

• 2 个状态(溢出 hidden/visible)

打开和关闭总是在动画开始时切换,而 hidden/visible 状态在动画结束时有不同的处理方式。

注意:你会看到一个#main-menu 元素:它是一个 UL,在 y 轴上有转换的翻译,因为整个东西都是菜单 slide-down/up 效果。

    @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

• 汉堡包是一个简单的 on/off 按钮

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

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

这对我有用。

在大多数现代浏览器中,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 剪辑了 整个 元素。这意味着如果您有边框、框阴影等,它们也会被剪掉。根据容器的设计,有时可以通过将剪辑应用于子包装元素来解决这个问题。