Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS 奇技淫巧:动态高度过渡动画 #91

Open
chokcoco opened this issue Jan 11, 2021 · 5 comments
Open

CSS 奇技淫巧:动态高度过渡动画 #91

chokcoco opened this issue Jan 11, 2021 · 5 comments

Comments

@chokcoco
Copy link
Owner

chokcoco commented Jan 11, 2021

这个问题源自于掘金上的一个留言,一个朋友问到,为什么我下面这段代码的高度过渡动画失效了?

伪代码大概是这样:

{
    height: unset;
    transition: all 0.3s linear;
    will-change: height;

    &.up {
        height: 0;
    }
    &.down {
        height: unset;
    }
}

把它还原成一个实际的 Demo,效果大概是这样(本质想的想法是通过给元素切换它的 .up.down 类,让它实现展开、合上的动画 ):

heightransition1

嗯哼?很奇怪,明明给 height 属性设置了 transition,为什么过渡动画没有触发,而是直接一步到位展开了呢?

我们期待的效果是这样的:

heightransition2

transition 不支持 height: auto

当上述代码设置成 height: unset 时,实际等同于设置了 height: auto,我们的想法是希望这段代码能够容器支持文本的动态高度。每次展开的时候,过渡展开到容器本身的高度即可。

查看规范,究其原因,在于 CSS transtion 不支持元素的高度为 auto 的变化

如果把上述的 height: unset 替换成一个具体的高度值,则动画是生效的,譬如:

{
    &.up {
        height: 0;
    }
    &.down {
      - height: unset;
      + height: 500px;
    }
}

heightransition3

但是,我们又希望能够做到动态高度的过渡转换,是不是就没有办法了么?

巧用 max-height 适配动态高度

嘿嘿,这里有一个非常有意思的小技巧。既然不支持 height: auto,那我们就另辟蹊径,利用 max-height 的特性来做到动态高度的伸缩。

我们改造一下上述代码,将 height: 0 替换为 max-height: 0,将 height: auto 替换成 max-height: 1000px,伪代码大概是这个意思:

{
    max-height: 0;
    transition: max-height 0.3s linear;

    &.up {
        max-height: 0;
    }
    &.down {
        max-height: 1000px;
    }
}

我们估算一下实际容器的最大高度,这里的 1000px 只需要比最大高度高即可。但是这里不能设置的太高,最高是贴近最大的使用高度即可,后面会聊到为什么。

由于 max-height 只是限制文本的最大高度,当容器的实际高度没有达到限制的最大高度,将不会继续变高,看看效果:

heightransition4

CodePen Demo -- the height property transition unwork

小缺陷

整体效果还是非常的 Nice 的,当然,可能有两个小缺陷,

  1. 如果实际场景中 max-height 需要用到并且有其它作用,那么可能这种方法就无法满足需求了
  2. 另一个缺点就是视觉上有延迟,和实际高度相差越大越明显。也就是说,如果容器实际高度只有 200px,max-height 为 1000px,动画时间为 1s,缓动函数为 linear。实际动画从 0 到 200px 的高度过渡时间只有 0.2s,这一点需要非常注意~

因为本来展开动画是期望将容器的高度用 1s 的时间拉伸至 1000px,实际在 200px 的时候就停止了,所以动画时间只有 0.2 秒。综上,方法是好方法,但是具体使用的时候要需要具体分析。

最后

好了,一个小细节,希望对你有所帮助,本文到此结束,希望对你有帮助 :),想 Get 到最有意思的 CSS 资讯,千万不要错过我的 iCSS 公众号 😄

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

@chokcoco chokcoco changed the title CSS 技巧一则:height 过渡动画 CSS 技巧一则:动态高度过渡动画 Jan 12, 2021
@Tonysmark
Copy link

🤞 (๑•̀ㅂ•́)و✧

@fightingcat
Copy link

max-height 还一个缺点就是视觉上有延迟,和实际高度相差越大越明显……

@chokcoco
Copy link
Owner Author

@fightingcat 试了下 还真是 感觉是个很影响实际使用的点

@chokcoco chokcoco changed the title CSS 技巧一则:动态高度过渡动画 CSS 奇技淫巧:动态高度过渡动画 Jan 13, 2021
@smiler-rf
Copy link

使用max-height,为什么收缩过程的时间与设置的动画时间相等呢,而不是小于,动画不是作用在max-height上了吗,虽然容器实际展开高度只有200px

@adouni1996
Copy link

利用max-height实现展开和收缩动画有一个无法规避的缺陷:
多个高度不确定的块一起渲染,都需要用到这个展开和收缩的动画,那么max-height最合理的值是多少?
倘若有一个块的高度是50px,另一个块的高度是1000px
对于1000px的块来说,max-height的值为1000px是最合理的
但对于50px的块,max-height设置为1000px,会对用户体验造成极大的影响
所以利用单一的max-height值进行展开和收缩控制,并不适用于有多个高度不确定块的场景

多个高度不确定块,要实现展开收缩动画的功能,合理的解决方案应该是:
用js动态获取每个块的实际高度
利用js控制块展开和收缩前后的height
配合transition属性进行动画控制

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants