J'essaie de créer un hamburger animé en utilisant le CSS. Pour ce faire, j'utilise trois span différents et j'anime au clic - rien de spécial.

Mais d'une manière ou d'une autre, l'origine de la transformation est foirée, donc je ne peux pas former un X propre. Comment puis-je faire?

let active = false;

const handleNav = () => {
  const hamburger = document.querySelector(".hamburger");
  if (!active) {
    hamburger.classList.add("is-active");
  } else {
    hamburger.classList.remove("is-active");
  }
  
  active = !active;
}
.hamburger {
  width: 25px;
  cursor: pointer;
}

span {
    display: block;
    width: 100%;
    height: 2px;
    background-color: black;
    margin-bottom: 4px;
    transform-origin: 0 50%;
    transition: all 0.3s;
}

span:last-child {
  margin-bottom: 0;
}

.is-active span:first-child {
  transform: rotate(45deg);
}

.is-active span:nth-child(2) {
  width: 0;
}

.is-active span:last-child {
  transform: rotate(-45deg);
}
<div class="hamburger" onclick="handleNav()">
    <span></span>
    <span></span>
    <span></span>
</div>
0
Tom 30 mai 2020 à 17:23

3 réponses

Meilleure réponse

Une façon est de masquer le hamburger et d'afficher l'icône de fermeture.

Une autre méthode consiste à calculer la largeur requise pour créer une icône de fermeture parfaite et à définir la largeur lorsqu'elle est active. Ici, la largeur est d'environ 17. Voir le code ci-dessous.

let active = false;

const handleNav = () => {
  const hamburger = document.querySelector(".hamburger");
  if (!active) {
    hamburger.classList.add("is-active");
  } else {
    hamburger.classList.remove("is-active");
  }
  
  active = !active;
}
.hamburger {
  width: 25px;
  cursor: pointer;
}

span {
    display: block;
    width: 100%;
    height: 2px;
    background-color: black;
    margin-bottom: 4px;
    transform-origin: 0 50%;
    transition: all 0.3s;
}

span:last-child {
  margin-bottom: 0;
}

.is-active span:first-child {
  transform: rotate(45deg);
  width: 17px
}

.is-active span:nth-child(2) {
  width: 0;
}

.is-active span:last-child {
  transform: rotate(-45deg);
  width: 17px
}
<div class="hamburger" onclick="handleNav()">
    <span></span>
    <span></span>
    <span></span>
</div>
0
upender 30 mai 2020 à 14:41

Si vous pouvez apporter des modifications mineures à la conception, modifiez height et margin-bottom de span.

span{
    height: 3px;
    margin-bottom: 6px;
}

Ou traduisez légèrement la première et la dernière mesure:

.is-active span:first-child {
  transform: rotate(45deg) translate(0,-3px);
}

.is-active span:last-child {
  transform: rotate(-45deg) translate(0,3px);
}
0
pagalprogrammer 30 mai 2020 à 14:38

Comme mentionné dans le commentaire, vous devez changer transform-origin pour les <span> s à la bonne valeur, voici un extrait:

let active = false;

const handleNav = () => {
  const hamburger = document.querySelector(".hamburger");
  if (!active) {
    hamburger.classList.add("is-active");
  } else {
    hamburger.classList.remove("is-active");
  }
  
  active = !active;
}
.hamburger {
  width: 25px;
  cursor: pointer;
}

span {
    display: block;
    width: 100%;
    height: 2px;
    background-color: black;
    margin-bottom: 4px;
    transform-origin: 17%;
    transition: all 0.3s;
}

span:last-child {
  margin-bottom: 0;
}

.is-active span:first-child {
  transform: rotate(45deg);
}

.is-active span:nth-child(2) {
  width: 0;
}

.is-active span:last-child {
  transform: rotate(-45deg);
}
<div class="hamburger" onclick="handleNav()">
    <span></span>
    <span></span>
    <span></span>
</div>
0
ROOT 30 mai 2020 à 14:38
62103793