我能否将CSS过渡应用于溢出属性?

37

我想通过给 body 添加类名的方式,为 div 点击时的 overflow 属性设置 transition-delay,实现过渡效果,代码如下:

$("div").click(function(){
    $("body").addClass("no_overflow");
});
div{
  background:lime;
  height:2000px;
}
.no_overflow{  
 overflow:hidden;
}
body{  
  overflow:auto;
  transition: overflow 0 2s;  
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>I'm div</div>

然而,这似乎不起作用(没有延迟)。我在这里做错了什么吗?
我知道可以使用 setTimeout 函数来实现这一点,但是想知道为什么不能使用 CSS 过渡来实现?CSS 过渡可以应用于哪些特定的样式属性吗?

2
我想到一个替代方案,你可以过渡 height 属性而不是 overflow 属性,以达到大致相同的外观。 - TylerH
1
@TylerH:是的,可以尝试一下。但是必须注意浏览器的高度才能这样做。此外,当overflowhidden时,它不会以相同的方式裁剪窗口。无论如何,我最终使用了setTimeout。;) - Nikunj Madhogaria
6个回答

61

有许多属性无法进行过渡。其中overflow就是其中之一;渲染引擎不知道如何在“隐藏”和“显示”之间进行过渡,因为这些是二进制选项,而不是区间。这也是为什么您不能在display: none;display: block;(例如)之间进行过渡的原因:没有中间阶段可用作过渡。

你可以在Mozilla开发者网络这里看到可以进行动画处理的属性列表。


据我所知,唯一的例外是visibility,因为你只能使用visiblehiddencollapse,意味着没有中间状态,但它仍然遵循动画步骤;这对于动画子菜单非常有效。 - Smithee
@Smithee 我不确定你在说 visibility 属性是唯一例外的意思。有多个(n > 1)属性可以过渡,也有多个(n > 1)不能过渡。 - TylerH

44

您可以使用 animation 来模拟延迟:

$("div").click(function() {
  $("body").addClass("no_overflow");
});
div {
  background: lime;
  height: 2000px;
}

.no_overflow {
  overflow: hidden;
  /* persist overflow value from animation */
  animation: 7s delay-overflow;
}

body {
  overflow: auto;
}

@keyframes delay-overflow {
  from { overflow: auto; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>I'm div</div>

如果您想对 .body 应用延迟删除类的动画效果,您将需要应用单独的动画。同时还要注意两个动画不重叠,否则它们会相互抵消。


3
太好了!我正在寻找一种方法来隐藏模态框上的滚动条,直到模态框淡入过渡完成。虽然有些方法可能不太正规,但这种方法确实解决了问题。 - Florian
这就是它!不要说“不能使用过渡效果进行动画处理”,给出一个只使用CSS的可行解决方案。 - benzkji
是的,这是唯一正确的答案。它有效! - Olgierd Dzięcielski
多么神奇... - Kamol

8

overflow 不是 CSS 可动画化属性。您可以在此处查看可动画化的 CSS 属性列表。


4
如果有人像我一样正在寻找一种动画裁剪需要溢出的元素的方法,这里是适合我的解决方案:使用clip-path CSS 属性进行动画处理,它在使用中非常灵活。
以下是一个很棒的工具,可以玩弄它,以便获取动画的正确起始/结束值:https://bennettfeely.com/clippy/

3

作为一种纯CSS解决方案,Dmitry的回答应该是唯一被采纳的答案,它可以对“不可动画化”的属性应用延迟。但值得一提的是,应用动画的CSS规则应该在每次需要时都能被“触发”。

例如,以下代码将不起作用:

@keyframes show-overflow {
  from { overflow: hidden; }
}
.hideable, .overlay {
  font-size: 36px;
  height: 50px;
}
.hideable {
  transition: height 2s;
  overflow: visible;
  animation: show-overflow 2s;  /* this line should be in separate  "triggerable" CSS rule to work */
}
.hideable.hidden {
  height: 0;
  overflow: hidden;
}
<button onclick="document.getElementById('hideable').classList.toggle('hidden')">
  Clik HERE to hide/show the text below
</button>
<div id='hideable' class='hideable'>
  This is the text to hide and show.  
</div>
<div class='overlay'>
  This is overlaying text
</div>

但是将标记属性移到单独的CSS规则后,一切都按预期工作:

@keyframes show-overflow {
  from { overflow: hidden; }
}
.hideable, .overlay {
  font-size: 36px;
  height: 50px;
}
.hideable {
  transition: height 2s;
  overflow: visible;
}
.hideable:not(.hidden) {
  animation: show-overflow 2s;  /* now this works! */
}
.hideable.hidden {
  height: 0;
  overflow: hidden;
}
<button onclick="document.getElementById('hideable').classList.toggle('hidden')">
  Clik HERE to hide/show the text below
</button>
<div id='hideable' class='hideable'>
  This is the text to hide and show.  
</div>
<div class='overlay'>
  This is overlaying text
</div>


1

在二进制属性之间,例如overflow: hidden;overflow: visible,无法进行过渡是有道理的,但如果不是“过渡”,而是像以下js伪代码一样就好了:

setTimeout("applyOverflowVisible()", transitionTime);

当然,您可以在JavaScript中自行完成此操作,但这样会将代码分散到不同的地方,可能会让其他人难以理解。我想使用像React这样的东西有所帮助,但即使如此,我也希望避免将css混合到js中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接