【问题标题】:CSS Transitions not working after converting from jQuery to Vanilla JS从 jQuery 转换为 Vanilla JS 后 CSS 转换不起作用
【发布时间】:2021-03-11 14:46:48
【问题描述】:

我最近决定将 <head> 中的旧代码从 jQuery 转换为 Vanilla JS。 基本上,当您单击汉堡时,移动菜单会淡入显示,并且所有链接转换都应该开始。我试图用一个简单的不透明度转换“替换”fadeToggle() 函数添加类mob-menu-show,但它不起作用,对于以前使用jQuery 的所有链接traslate 转换都是一样的。使用 jQuery,我完全没有问题,每次打开移动菜单时都会运行过渡。我认为这与以某种方式不执行转换的 JS 代码有关,因为 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');
  });
});

【问题讨论】:

  • 不相关但专业提示:使用$ 而不是jQuery,因为这样可以节省打字时间。
  • 嗨。在您的 js 中,您提出了一个参考 querySelector('.hamburger') 。 html中没有class hamburger。
  • @bron 我已经添加了它,我正在为汉堡包使用这个外部样式表jonsuh.com/hamburgers

标签: javascript html jquery css css-transitions


【解决方案1】:

正如其他人所提到的,带有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>

【讨论】:

  • 完美,它对所有人来说都是一种魅力。我知道,通过注入 JS 的转换,我必须给浏览器时间来处理它们。我通过为这些类设置超时来解决。我遵循了第二种方法,因为第一种方法根本不起作用。我还将visibility 属性用于.mobile-menu.mob-menu-show,不再使用display 之一。非常感谢您的解释。
【解决方案2】:

使用visibility: hidden;

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

【讨论】:

  • 不幸的是,将mobile-menu 设置为hiddenmob-menu-show 设置为visible,不再显示菜单。无论如何,感谢您的帮助。
  • 将显示设置为阻止/无并使用不透明度进行过渡是否不起作用?还是您遇到与可见性相同的问题?所以不透明度只是为了美观(褪色)而显示器隐藏/显示菜单? (或者根本不显示?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 2016-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多