CSS transition-behavior让display none也有动画效果

这篇文章发布于 2024年06月30日,星期日,00:55,归类于 CSS相关。 阅读 2408 次, 今日 18 次 2 条评论

 

水果西瓜封面占位图

一、现状描述

有一个元素设置了display:none隐藏,然后使用JS让其实现的时候,希望同时有透明度变化的动画效果,使用transition属性是无效的。

如下代码示意:

<div id="element" class="element">占位内容</div>
.element {
  display: none;
  opacity: 0;
  transition: .2s;
}
.element.active {
  display: block;
  opacity: 1;
}
// 让元素显示
element.classList.add('active');

此时元素是突然显示,而不是有透明度动画。

在之前,有两种方法:

  1. 元素先显示,透明度保持0,然后在下一个渲染绘制执行设置透明度为1.
  2. 使用CSS animation动画,代码参见:
    .element.active {
      display: block;
      animation: fadeIn .2s both;
    }
    @keyframes {
      from { opacity: 0; }
      to { opacity: 1; }
    }

不过上面两种方法都比较麻烦,不如直接一个transition属性来的方便。

那有没有什么办法让元素从display:none到display:block变化的时候,也有动画效果呢?

可以,最近各个现代浏览器支持了一个新的 CSS 属性名为transition-behavior,可以实现这样的需求。

二、transition-behavior属性的语法和作用

语法如下:

transition-behavior: allow-discrete;
transition-behavior: normal;

其中:

  • allow-discrete表示允许离散的CSS属性也支持transition过渡效果,其中,最具代表性的离散CSS属性莫过于display属性了。
  • normal就是之前的transition过渡表现,除了visibility这个我一直都认为是离散CSS的属性之外,其余离散CSS都没有过渡效果。,

使用案例

仅使用transition属性,实现元素从 display:inline ↔ none 的过渡效果。

HTML如下所示:

<button id="trigger">图片显示与隐藏</button>
<img id="target" src="1.jpg" />

通过toggle hidden属性实现显隐变化:

trigger.onclick = function () {
    target.toggleAttribute('hidden');	
};

OK,最关键的CSS来了,很简单,几行代码就可以了:

img {
    transition: .25s allow-discrete;
    opacity: 1;
}

img[hidden] {
    opacity: 0;
}

此时,点击按钮让图片隐藏的时候,就可以看到图片淡出的效果了,如下GIF动图所示:

图片隐藏动画示意

酷啊~

当然,上面的CSS代码也可以分开书写:

transition-duration: .25s;
transition-behavior: allow-discrete;

然而,再次点击按钮,希望其淡出显示的时候,却没有任何动画效果

问题分析与解决

为何设置transition-behavior:allow-discrete可以让动画display:none在过渡时长结束之后才执行,因此,opacity的过渡动画可以肉眼可见。

但是从display:nonedisplay:block的显示是突然的,在浏览器的渲染绘制层面,元素display计算值变成block和opacity设为1是在同一个渲染帧完成的,由于没有起始opacity,所以看不到动画效果。

那有没有什么办法让元素display显示的时候也有过渡效果呢?

还真有,可以使用全新的@starting-style规则,专门解决此类问题的。

三、使用@starting-style规则声明过渡起点

@starting-style顾名思义就是声明起始样式,专门用在transition过渡效果中。

例如上面的例子,要想让元素display显示的时候有淡出效果,很简单,再加三行代码就可以了:

img {
    transition: .25s allow-discrete;
    opacity: 1;
    @starting-style {
      opacity: 0;
    }
}

或者不使用CSS嵌套语法,这样写也是可以的:

img {
  transition: .25s allow-discrete;
  opacity: 1;
}
@starting-style {
  img {
    opacity: 0;
  }
}

此时,我们再点击按钮让图片显示,就可以看到图片是透明度动画显示的,如下MP4视频录屏所示(不动点击播放):

眼见为实,您可以狠狠地点击这里:CSS transition-behavior和@starting-style实现淡入淡出demo

不仅可以看到淡入淡出效果,还可以看到上面展示的仅淡出效果。

四、CSS越来越强了

本文要介绍的其实就2个东西,一个是transition-behavior:allow-discrete可以让元素display:none也可以有淡出效果,另外一个是@starting-style规则,可以让元素不再是display:none可以有淡入效果。

在实际的Web开发中,popover浮层和dialog对话框显隐的时候,都是基于display计算值实现的。

现在,有了transition-behavior@starting-style规则,这些原生HTML元素的交互效果就可以更上一层楼,算是弥补了长久以来的不足,非常棒,CSS果然是越来越强了。

继续学习,保持不懈。

顺便帮忙下,谢啦~

谢啦

(本篇完)

分享到:


发表评论(目前2 条评论)

  1. codehz说道:

    @starting-style有个巨坑,虽然可以嵌套(而且支持@starting-style的浏览器一定支持css嵌套)
    但,伪元素里不能嵌套!也就是dialog的::backdrop里写不了@starting-style!!!!得单独再外面写

  2. CaptainOfPhB说道:

    大佬太强啦!