Помогите новичку. Бургер меню

Пытаюсь сделать анимацию для кнопки бургер меню. По идеи сначала должны линии идти к центральной линии (плавно) а потом поворачиваться на 45 градусов (тоже плавно). На деле же первая часть анимации попросту не срабаывает, а вторая срабатывает. (Если отключить воторую часть анимации то первая сработает). Как сделать так что бы они работали вместе? (Чтобы отключить вотрую часть анимации надо удалить стили где есть класс ".menu-line")

document.querySelector('.menu-btn').addEventListener('click', (e) => {
    let menuBtn = document.querySelector('.menu-btn');

    if (menuBtn.classList.contains("isActive")) {
        menuBtn.classList.remove("isActive");
    } else {
        menuBtn.classList.add("isActive");
    }
})
* {
    margin: 0;
    padding: 0;
}

.menu-btn {
    font-size: 0;
    width: 50px;
    height: 50px;
    outline: none;
    background: red;
    border: none;
    position: relative;
    cursor: pointer;
}

.menu-btn span {
    position: absolute;
    height: 2px;
    width: 24px;
    background: white;
    left: 13px;
    top: 23px;
}

.menu-btn span::before, .menu-btn span::after {
    display: block;
    position: absolute;
    height: 2px;
    width: 24px;
    background: white;
    content: "";
}

.menu-btn span::before {
    right: 0;
    bottom: 10px;
    transition-property: bottom;
    transition-timing-function: ease;
    transition-duration: 0.3s, 0.3s;
}

.menu-btn span::after {
    left: 0;
    top: 10px;
    transition-property: top;
    transition-timing-function: ease;
    transition-duration: 0.3s;
}

.menu-btn.isActive span::before {
    bottom: 0;
}

.menu-btn.isActive span:after {
    top: 0;
}

.menu-line span::before {
    transition-property: transform;
    transition-timing-function: ease;
    transition-duration: 0.3s;
    transition-delay: 0.3s;
}

.menu-line span::after {
    transition-property: transform;
    transition-timing-function: ease;
    transition-duration: 0.3s;
    transition-delay: 0.3s;
}

.menu-line.isActive span::before {
    transform: rotate(45deg);
}

.menu-line.isActive span:after {
    transform: rotate(-45deg);
}

.menu-line.isActive span {
    background: none;
    transition: background 0s 0.3s;
}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="main.css">
</head>
<body>

    <div class="menu">
        <button class="menu-btn menu-line">
            <span>Меню</span>
        </button>
    </div>

    <script src="script.js"></script>
</body>
</html>


Ответы (1 шт):

Автор решения: Neverm1ndo

Может не совсем элегантное решение, но работает. Я использовал css анимации @keyframes и свойство animation. Разные анимации для 2 классов isActive и notActive, которые переключаются по событыю клика в JS.

document.querySelector('.menu-btn').addEventListener('click', function(_e) {
  this.classList.toggle("isActive");
  this.classList.remove("notActive"); 
  if (!this.classList.contains("isActive")) this.classList.add("notActive");
});
* {
    margin: 0;
    padding: 0;
}

.menu-btn {
    font-size: 0;
    width: 50px;
    height: 50px;
    outline: none;
    background: red;
    border: none;
    position: relative;
    cursor: pointer;
}

.menu-btn span {
    position: absolute;
    height: 2px;
    width: 24px;
    background: white;
    left: 13px;
    top: 23px;
    transition-timing-function: ease;
    transition-duration: 0.3s;
}

.menu-btn span::before, .menu-btn span::after {
    display: block;
    position: absolute;
    height: 2px;
    width: 24px;
    background: white;
    content: " ";
    transition-timing-function: ease;
    transition-duration: 0.3s;
}

.menu-btn span::before {
    right: 0;
    bottom: 10px;
    transition-property: bottom;
}

.menu-btn span::after {
    left: 0;
    top: 10px;
    transition-property: top;
}

@keyframes clockwise {
  0% {
    bottom: 10px;
    transform: rotate(0deg);
  }
  50% {
    bottom: 0px;
    transform: rotate(0deg);
  }
  80% {
    transform: rotate(0deg); 
  }
  100% { 
    transform: rotate(45deg); 
  }
}
@keyframes counterclockwise {
  0% {
    top: 10px;
  }
  50% {
    top: 0px;
    transform: rotate(0deg); 
  }
  90% {
    transform: rotate(0deg); 
  }
  100% { 
    transform: rotate(-45deg); 
  }
}

@keyframes clockwiseback {
  0% {
    transform: rotate(45deg);
  }
  50% {
    transform: rotate(0deg);
  }
  70% {
    bottom: 0px;
  }
  100% { 
    bottom: 10px;
  }
}
@keyframes counterclockwiseback {
  0% {
    transform: rotate(-45deg); 
  }
  50% {
    transform: rotate(0deg); 
  }
  70% {
    top: 0px;
  }
  100% { 
    top: 10px;
  }
}


.menu .isActive span::before {
  bottom: 0;
  animation: .3s clockwise ease;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
}

.menu .isActive span:after {
  top: 0;
  animation: .3s counterclockwise ease;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
}

.menu .notActive span::before {
  bottom: 0;
  animation: .3s clockwiseback ease;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
}

.menu .notActive span:after {
  top: 0;
  animation: .3s counterclockwiseback ease;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
}

.menu .isActive span {
   background: transparent;
}
<html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport"
            content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <link rel="stylesheet" href="main.css">
  </head>
  <body>
    <div class="menu">
      <button class="menu-btn menu-line">
          <span>Меню</span>
      </button>
    </div>
  </body>
</html>

Можно еще использовать Element.animate() в связке с svg, но это уже другая история.

→ Ссылка