IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    张 鑫旭发表于 2024-06-29 16:55:20
    love 0

    by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11245
    本文可全文转载,独立域名个人网站无需授权,但需要保留原作者、出处以及文中链接,任何网站均可摘要聚合,商用请联系授权。

    水果西瓜封面占位图

    一、现状描述

    有一个元素设置了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:none到display: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果然是越来越强了。

    继续学习,保持不懈。

    顺便帮忙下,谢啦~

    谢啦

    本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
    本文地址:https://www.zhangxinxu.com/wordpress/?p=11245

    (本篇完)



沪ICP备19023445号-2号
友情链接