CSS 从 jQuery 转换为 Vanilla JS 后转换不起作用

CSS Transitions not working after converting from jQuery to Vanilla JS

我最近决定将 <head> 中的旧代码从 jQuery 转换为 Vanilla JS。 基本上,当您单击汉堡包时,移动菜单会淡入显示,并且所有链接过渡都应该开始。我试图用一个简单的不透明度转换来“替换”添加 class mob-menu-showfadeToggle() 函数,但它不起作用,对于之前工作的所有链接 traslate 转换都是一样的jQuery。使用 jQuery 我一点问题都没有,每次我打开移动菜单时,转换都会使用 运行。我认为这与以某种方式不执行转换的 JS 代码有关,因为 class mobile-menu-animations 它实际上被触发了,因为我可以看到正确的不透明度。感谢您的帮助,如果代码混乱,我很抱歉,我现在才开始。

HTML

<button class="hamburger hamburger--3dxy" type="button" aria-label="Menu" aria-controls="navigation">
  <span class="hamburger-box">
    <span class="hamburger-inner"></span>
  </span>
</button>

<div id="nav-fullscreen" class="mobile-menu mobile-menu-controls">
  <div id="mobile-menu-container">
    <div id="mobile-menu-content">
      <div id="logo-menu">
        <div id="logo-mobile-menu"><a href="https://#"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 69.5 8.57" class="logo">...</svg> </a></div>
      </div>
      <div id="nav-items">
        <div id="navigation">
          <ul>
            <li><a href="https://#">Item 1</a></li>
            <li><a href="https://#">Item 2</a></li>
            <li><a href="https://#">Item 3</a></li>
            <li><a href="https://#">Item 4</a></li>
          </ul>
        </div>
      </div>
      <div id="menu-mobile-button-cont"><a id="button-mobile-menu" href="#">Buy Now</a></div>
    </div>
  </div>
</div>

CSS

    .mobile-menu {
        display: none;
        opacity: 0;
        transition: opacity 0.2s;
    }
    
    .mob-menu-show {
      display: block !important;
      opacity: 1;
      transition: 0.2s opacity;
    }
    
    .mobile-menu-controls {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        background-color: #fff;
        z-index: 15;
    }
    
    #mobile-menu-container {
        flex-direction: column;
        display: flex;
        width: 100%;
        height: 100vh;
        align-items: stretch;
        top: 0;
        text-align: left;
        overflow-x: hidden;
        overflow-y: scroll;
    }
    
    #mobile-menu-content {
        width: 100%;
        flex-direction: column;
        display: flex;
        align-items: stretch;
        max-width: 1280px;
    }
    
    #nav-items {
        flex-direction: unset;
        margin-top: 7rem;
    }
    
    #menu-mobile-button-cont {
        margin-left: 20px;
        margin-bottom: 26px;
        margin-right: 20px;
        text-align: left;
        flex-direction: unset;
        display: flex;
        width: 100%;
        margin-top: 8rem;
    }

/* Transitions */
    
    #button-mobile-menu {
        opacity: 0;
        margin-left: 40px;
        transform: translateX(0px);
        transition: transform .2s,opacity .2s;
    }
    
    #logo-mobile-menu {
      opacity: 0;
      padding-left: 40px;
      transform: translateX(0px);
      transition: transform 0.2s, opacity 0.2s;
    }
    
    .mobile-menu-controls li {
      opacity: 0;
      padding-left: 40px;
      transform: translateX(0px);
      transition: transform 0.2s, opacity 0.2s;
    }
    
    #button-mobile-menu {
      opacity: 0;
      margin-left: 40px;
      transform: translateX(0px);
      transition: transform 0.2s, opacity 0.2s;
    }
    
    .mobile-menu-animations #logo-mobile-menu {
        transform: translateX(-40px);
        transition: transform 0.2s, opacity 0.2s;
        transition-timing-function: ease, ease;
        opacity: 1;
        transition-delay: 0.1s;
    }
    
    .mobile-menu-animations li {
        transform: translateX(-40px);
        transition: transform 0.2s, opacity 0.2s;
        transition-timing-function: ease, ease;
        opacity: 1;
    }
    
    .mobile-menu-animations li:nth-child(1) {
        transition-delay: 0.2s;
    }
    
    .mobile-menu-animations li:nth-child(2) {
        transition-delay: 0.3s;
    }
    
    .mobile-menu-animations li:nth-child(3) {
        transition-delay: 0.4s;
    }
    
    .mobile-menu-animations li:nth-child(4) {
        transition-delay: 0.5s;
    }
    
    .mobile-menu-animations #button-mobile-menu {
        transform: translateX(-40px);
        transition: transform 0.2s, opacity 0.2s;
        transition-timing-function: ease, ease;
        opacity: 1;
        transition-delay: 0.6s;
    }
    
/* Prevent body scroll */

    .prevent-scroll {
      overflow: hidden;
    }

旧jQuery代码

$(document).ready(function() {
  $('.hamburger').click(function() {
    $('.hamburger').toggleClass('is-active');
    $('.mobile-menu').fadeToggle(350);
    $('.mobile-menu-controls').toggleClass('mobile-menu-animations');
    $('body').toggleClass("prevent-scroll");
  });
});

转换后的 JS

document.addEventListener("DOMContentLoaded", function(event) { 

  let hamb = document.querySelector('.hamburger')
  let mobmenu = document.querySelector('.mobile-menu')
  let mobanim = document.querySelector('.mobile-menu-controls')
  let bdy = document.querySelector('body')

  hamb.addEventListener('click', function(e) {
      this.classList.toggle('is-active');
      mobmenu.classList.toggle('mob-menu-show');
      mobanim.classList.toggle('mobile-menu-animations');
      bdy.classList.toggle('prevent-scroll');
  });
});

使用visibility: hidden;

display: none. 无法很好地执行转换。

正如其他人所提到的,具有 display css 属性的转换有点糟糕。不过,您可以使用 keyframesanimations 来解决这个问题。您将需要更新其他过渡以使用 keyframes,而在本示例中我只将动画设置为 opacity

let hamb = document.querySelector('.hamburger')
let mobmenu = document.querySelector('.mobile-menu')
let mobanim = document.querySelector('.mobile-menu-controls')
let bdy = document.querySelector('body')

hamb.addEventListener('click', function() {
  hamb.classList.toggle('is-active');
  bdy.classList.toggle('prevent-scroll');
  mobmenu.classList.toggle('mob-menu-show');
  mobanim.classList.toggle('mobile-menu-animations');
});
@keyframes fade {
  0% {
    opacity: 0;
  }
}

.mobile-menu {
  display: none;
}

.mob-menu-show {
  opacity: 1;
  display: block;
  animation: fade .250s both;
}

.mobile-menu-controls {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  background-color: #fff;
}

#mobile-menu-container {
  flex-direction: column;
  display: flex;
  width: 100%;
  height: 100vh;
  align-items: stretch;
  top: 0;
  text-align: left;
  overflow-x: hidden;
  overflow-y: scroll;
}

#mobile-menu-content {
  width: 100%;
  flex-direction: column;
  display: flex;
  align-items: stretch;
  max-width: 1280px;
}

#nav-items {
  flex-direction: unset;
  margin-top: 7rem;
}

#menu-mobile-button-cont {
  margin-left: 20px;
  margin-bottom: 26px;
  margin-right: 20px;
  text-align: left;
  flex-direction: unset;
  display: flex;
  width: 100%;
  margin-top: 8rem;
}


/* Transitions */

#button-mobile-menu {
  opacity: 0;
  margin-left: 40px;
  transform: translateX(0px);
  transition: transform .2s, opacity .2s;
}

#logo-mobile-menu {
  opacity: 0;
  padding-left: 40px;
  transform: translateX(0px);
  transition: transform 0.2s, opacity 0.2s;
}

.mobile-menu-controls li {
  opacity: 0;
  padding-left: 40px;
  transform: translateX(0px);
  transition: transform 0.2s, opacity 0.2s;
}

#button-mobile-menu {
  opacity: 0;
  margin-left: 40px;
  transform: translateX(0px);
  transition: transform 0.2s, opacity 0.2s;
}

.mobile-menu-animations #logo-mobile-menu {
  transform: translateX(-40px);
  transition: transform 0.2s, opacity 0.2s;
  transition-timing-function: ease, ease;
  opacity: 1;
  transition-delay: 0.1s;
}

.mobile-menu-animations li {
  transform: translateX(-40px);
  transition: transform 0.2s, opacity 0.2s;
  transition-timing-function: ease, ease;
  opacity: 1;
}

.mobile-menu-animations li:nth-child(1) {
  transition-delay: 0.2s;
}

.mobile-menu-animations li:nth-child(2) {
  transition-delay: 0.3s;
}

.mobile-menu-animations li:nth-child(3) {
  transition-delay: 0.4s;
}

.mobile-menu-animations li:nth-child(4) {
  transition-delay: 0.5s;
}

.mobile-menu-animations #button-mobile-menu {
  transform: translateX(-40px);
  transition: transform 0.2s, opacity 0.2s;
  transition-timing-function: ease, ease;
  opacity: 1;
  transition-delay: 0.6s;
}


/* Prevent body scroll */

.prevent-scroll {
  overflow: hidden;
}
<button class="hamburger hamburger--3dxy" type="button" aria-label="Menu" aria-controls="navigation">
  <span class="hamburger-box">
    <span class="hamburger-inner"></span>
  </span>
</button>

<div id="nav-fullscreen" class="mobile-menu mobile-menu-controls">
  <div id="mobile-menu-container">
    <div id="mobile-menu-content">
      <div id="logo-menu">
        <div id="logo-mobile-menu">
          <a href="https://#"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 69.5 8.57" class="logo">...</svg> </a>
        </div>
      </div>
      <div id="nav-items">
        <div id="navigation">
          <ul>
            <li><a href="https://#">Item 1</a></li>
            <li><a href="https://#">Item 2</a></li>
            <li><a href="https://#">Item 3</a></li>
            <li><a href="https://#">Item 4</a></li>
          </ul>
        </div>
      </div>
      <div id="menu-mobile-button-cont"><a id="button-mobile-menu" href="#">Buy Now</a></div>
    </div>
  </div>
</div>

如果您不想设置所有过渡的关键帧,您可以使用 javascript 来使用此方法做同样的事情。

  1. 单击时,手动将 display 属性设置为 block
  2. 使用 setTimeout 等待我们的样式刷新到 DOM。
  3. 添加我们的类名。

let hamb = document.querySelector('.hamburger')
let mobmenu = document.querySelector('.mobile-menu')
let mobanim = document.querySelector('.mobile-menu-controls')
let bdy = document.querySelector('body')

hamb.addEventListener('click', function() {
  hamb.classList.toggle('is-active');
  bdy.classList.toggle('prevent-scroll');
  mobmenu.style.display = "block";

  setTimeout(() => {
    mobmenu.classList.toggle('mob-menu-show');
    mobanim.classList.toggle('mobile-menu-animations');
  });
});
.mobile-menu {
  display: none;
  opacity: 0;
  transition: opacity .250ms;
}

.mob-menu-show {
  opacity: 1;
}

.mobile-menu-controls {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  background-color: #fff;
}

#mobile-menu-container {
  flex-direction: column;
  display: flex;
  width: 100%;
  height: 100vh;
  align-items: stretch;
  top: 0;
  text-align: left;
  overflow-x: hidden;
  overflow-y: scroll;
}

#mobile-menu-content {
  width: 100%;
  flex-direction: column;
  display: flex;
  align-items: stretch;
  max-width: 1280px;
}

#nav-items {
  flex-direction: unset;
  margin-top: 7rem;
}

#menu-mobile-button-cont {
  margin-left: 20px;
  margin-bottom: 26px;
  margin-right: 20px;
  text-align: left;
  flex-direction: unset;
  display: flex;
  width: 100%;
  margin-top: 8rem;
}


/* Transitions */

#button-mobile-menu {
  opacity: 0;
  margin-left: 40px;
  transform: translateX(0px);
  transition: transform .2s, opacity .2s;
}

#logo-mobile-menu {
  opacity: 0;
  padding-left: 40px;
  transform: translateX(0px);
  transition: transform 0.2s, opacity 0.2s;
}

.mobile-menu-controls li {
  opacity: 0;
  padding-left: 40px;
  transform: translateX(0px);
  transition: transform 0.2s, opacity 0.2s;
}

#button-mobile-menu {
  opacity: 0;
  margin-left: 40px;
  transform: translateX(0px);
  transition: transform 0.2s, opacity 0.2s;
}

.mobile-menu-animations #logo-mobile-menu {
  transform: translateX(-40px);
  transition: transform 0.2s, opacity 0.2s;
  transition-timing-function: ease, ease;
  opacity: 1;
  transition-delay: 0.1s;
}

.mobile-menu-animations li {
  transform: translateX(-40px);
  transition: transform 0.2s, opacity 0.2s;
  transition-timing-function: ease, ease;
  opacity: 1;
}

.mobile-menu-animations li:nth-child(1) {
  transition-delay: 0.2s;
}

.mobile-menu-animations li:nth-child(2) {
  transition-delay: 0.3s;
}

.mobile-menu-animations li:nth-child(3) {
  transition-delay: 0.4s;
}

.mobile-menu-animations li:nth-child(4) {
  transition-delay: 0.5s;
}

.mobile-menu-animations #button-mobile-menu {
  transform: translateX(-40px);
  transition: transform 0.2s, opacity 0.2s;
  transition-timing-function: ease, ease;
  opacity: 1;
  transition-delay: 0.6s;
}


/* Prevent body scroll */

.prevent-scroll {
  overflow: hidden;
}
<button class="hamburger hamburger--3dxy" type="button" aria-label="Menu" aria-controls="navigation">
  <span class="hamburger-box">
    <span class="hamburger-inner"></span>
  </span>
</button>

<div id="nav-fullscreen" class="mobile-menu mobile-menu-controls">
  <div id="mobile-menu-container">
    <div id="mobile-menu-content">
      <div id="logo-menu">
        <div id="logo-mobile-menu">
          <a href="https://#"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 69.5 8.57" class="logo">...</svg> </a>
        </div>
      </div>
      <div id="nav-items">
        <div id="navigation">
          <ul>
            <li><a href="https://#">Item 1</a></li>
            <li><a href="https://#">Item 2</a></li>
            <li><a href="https://#">Item 3</a></li>
            <li><a href="https://#">Item 4</a></li>
          </ul>
        </div>
      </div>
      <div id="menu-mobile-button-cont"><a id="button-mobile-menu" href="#">Buy Now</a></div>
    </div>
  </div>
</div>