个人记录贴:JS小技巧---display显隐动画效果

1,273 阅读1分钟

今天记录一个js小技巧 既不用setTimeout 也不用监听transitioned事件 实现display:block/none的显示隐藏动画

准备工作

dom元素和css准备,先实现一个简单的弹窗样式和一个控制按钮,觉得繁琐的直接跳到第1步看核心代码,不心急吃热豆腐的可以跟着我一起回顾弹窗的垂直居中css实现方式


  <style>
    .content {
      /* 四行css实现垂直居中 */
      position: relative;
      top: 50%;
      left: 50%;
      transform: translateX(-50%) translateY(-50%);
      height: 200px;
      width: 200px;
      background-color: #fff;
    }
    .dialog {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.2);
      opacity: 0;
      display: none;
      transition: opacity 1s ease;
    }
    .dialog.block {
      display: block;
    }
    .dialog.visible {
      opacity: 1;
      transition: opacity 1s ease;
    }
  </style>
  
    <button type="button" onclick="change()">弹窗</button>
    <div class="dialog">
      <div class="content">
        <p>我是弹窗,嘿嘿</p>
      </div>
    </div>


  <body>
    <button type="button" onclick="change()">弹窗</button>
    <div class="dialog">
      <div class="content">
        <p>我是弹窗,嘿嘿</p>
      </div>
    </div>
  </body>

JS控制显示隐藏

我们都知道css的opacity、width、height、margin等属性可以通过transition实现过渡效果。 但是display确不行,背后到底隐藏了什么秘密目前我也没搞懂,其可能的原因是display设置为block后,浏览器将其渲染到页面的过程是ui render,这个过程是一个宏任务,而js会优先执行同步代码,所以先执行了opacity:1。 如果在设置了block后,立马获取元素的clientHeightoffsetHeight属性,就会先在页面绘制dialog,然后执行过度动画。这其中又是什么原理,我也没搞懂,暂时记录一下

      var dialogEl = document.querySelector(".dialog");
      function change() {
        dialogEl.classList.add("block");
        // 最关键的是这一步,可以保证元素先渲染到页面,再执行opacity:1,
        // 除此之外还有offsetWidth、scrollHeight均有相同的效果
        dialogEl.clientHeight;
        dialogEl.classList.add("visible");
      }

效果展示:

dialog.gif