Use neither setTimeout nor listening for transitioned events to display a hidden animation with display: block/ None

The preparatory work

Dom elements and CSS preparation, first to achieve a simple popover style and a control button, feel cumbersome directly jump to the first step to see the core code, not eager to eat hot bean curd can follow me to review the popover vertical centered CSS implementation


  <style>
    .content {
      /* Four lines of CSS are vertically centered */
      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()">Popup window</button>
    <div class="dialog">
      <div class="content">
        <p>I'm popover, hey, hey</p>
      </div>
    </div>


  <body>
    <button type="button" onclick="change()">Popup window</button>
    <div class="dialog">
      <div class="content">
        <p>I'm popover, hey, hey</p>
      </div>
    </div>
  </body>
Copy the code

JS controls show hide

We all know that CSS functions such as opacity, width, height and margin can be implemented using transition. The possible reason is that after display is set to block, the process of browser rendering it to the page is UI render. This process is a macro task, and JS will have priority to execute synchronous code, so it performs opacity first: 1. If the clientHeight and offsetHeight properties of the element are obtained immediately after the block is set, the dialog will be drawn on the page first, and then the overanimation will be performed. How does that work? I don’t understand it. Just for the moment, okay

      var dialogEl = document.querySelector(".dialog");
      function change() {
        dialogEl.classList.add("block");
        // The most critical step is this, which ensures that elements are rendered to the page before performing opacity: 1,
        // In addition to offsetWidth, scrollHeight have the same effect
        dialogEl.clientHeight;
        dialogEl.classList.add("visible");
      }
Copy the code

Effect display: