Reputation: 4033
I'm trying to build an animated hamburger using css. To do so I use three different span
and animate on click - nothing special.
But somehow the transform-origin whatsoever is messed up, hence I can't form a proper X
. How can I do so?
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>
Upvotes: 1
Views: 99
Reputation: 180
One way is to hide the hamburger and display close icon.
Other way is to calculate the width required to make a perfect close icon and set width when active. Here width is around 17. See the below code.
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>
Upvotes: 2
Reputation: 529
If you can make minor changes in design then change height
and margin-bottom
of span
.
span{
height: 3px;
margin-bottom: 6px;
}
or slightly translate first and last bar:
.is-active span:first-child {
transform: rotate(45deg) translate(0,-3px);
}
.is-active span:last-child {
transform: rotate(-45deg) translate(0,3px);
}
Upvotes: 0
Reputation: 11622
As mentioned in the comment, you have to change transform-origin
for the <span>
s to the right value, here is a snippet:
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>
Upvotes: 0