我需要为高度设置动画,并为第一个关键帧设置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
动画:没有
您还可以在MDN上查看可动画属性列表:Animated properties
解决方法:
如果需要更改overflow属性,可以使用JS。这是jQuery库的一个例子。
overflow属性随类切换而变化。单击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个状态(溢出隐藏/可见)
打开和关闭始终在animationstart上切换,而隐藏/可见状态在animationend上有不同的处理方式。
注意:你会看到一个#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');
}
});
这适合我。
在大多数现代浏览器中,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-path
和overflow
之间存在两个显着差异,这使得它在所有情况下都不适合。
首先,与overflow: visible
的元素不同,任何clip-path
的元素都有stacking context,因此渲染溢出内容的方式会有所不同 - 尽管在菜单内容丰富的情况下,你可能还是想要这个!
其次,与仅剪辑儿童的overflow
不同,clip-path
剪辑整个元素。这意味着如果你有边框,框阴影等,那些也会被剪裁。根据容器的设计,有时可以通过将夹子应用于子包装元件来解决这个问题。